65.9K
CodeProject 正在变化。 阅读更多。
Home

自动处理传入文件

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.18/5 (13投票s)

2007年10月27日

CPOL

2分钟阅读

viewsIcon

50124

downloadIcon

277

使用 DirectoryInfo 类而不是 FileSystemWatcher 自动处理传入文件。

引言

大家好。 这是一篇关于如何自动处理传入数据的文章。 近期,我看到很多人试图使用 FileSystemWatcher 来触发他们软件中的数据处理函数。 然而,其中许多人不得不处理异常:“进程无法访问该文件,因为它正被另一个进程使用”。 我们可以很容易地解决这个问题。 我们只需要创建一个不断读取目录的线程,使用 DirectoryInfo 类。 此外,我们创建一个 ProcessFile 函数,该函数处理文件并将其移动到“processed”(已处理)目录中。

使用代码

好了

private bool ProgramRunning = true;
private int FilesHandled = 1;

static void Main(string[] args)
{
    Program prog = new Program();
    prog.ReadDirectoryThread();
}

我使用字段 FilesHandled 来计算我处理的文件数量,以便我可以验证是否已处理所有文件。

private void ReadDirectoryThread()
{
    while (this.ProgramRunning)
    {
        DirectoryInfo DirInfo = new DirectoryInfo(
            Path.GetDirectoryName(
            Process.GetCurrentProcess().MainModule.FileName)
            + "\\incoming\\");
        foreach (FileInfo FInfo in DirInfo.GetFiles("*.xml"))
        {
            Thread t = new Thread(new ParameterizedThreadStart(ProcessFile));
            t.Start(FInfo.FullName);
            while (t.ThreadState != System.Threading.ThreadState.Stopped)
            {
                //Thread.Sleep(5);
            }
        }
    }
}

我们不断检查是否创建了新文件。 使用 GetFiles() 函数,您可以对特定文档类型设置筛选器,例如 XML 文件。 一旦目录包含文档,就会使用 ParameterizedThreadStart() 函数调用 ProcessFile 函数。 您可以在 t.ThreadState while 循环中添加 Thread.Sleep() 以降低 CPU 使用率; 但是,当您需要不断处理大量数据文件时,不建议这样做。

void ProcessFile(object FileToProcess)
{
    string sFile = FileToProcess.ToString();
    bool isProcessed = false;
    // File processing
    try
    {
        // Process your file here.
    }
    catch
    {
        return;
    }
    // After the file is processed, we move it
    while (!isProcessed)
    {
        try
        {
            string ProcessedFilesDir = string.Format("{0}\\processed\\{1}_{2}.xml",
                Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName),
                DateTime.Now.ToString("dd_MM_yyyy_HH_mm_ss"), Guid.NewGuid().ToString());
            File.Move(sFile, ProcessedFilesDir);
            Console.WriteLine(FilesHandled + " - File " + 
                              sFile.ToString() + " processed\n");
            FilesHandled++;
        }
        catch
        {
            isProcessed = false;
        }
        finally
        {
            isProcessed = true;
        }
    }
}

在上面的代码的第一部分,我们可以调用函数来处理我们的数据文件,例如,导入函数或任何其他函数。 在成功处理数据后,我们尝试将文件移动到“processed”(已处理)目录中。 如果文件具有独占权限,则线程会继续尝试移动文件,直到最终移动为止。

我遇到过一些每秒传入一百多个数据文件的情况。 因此,我添加了 DateTime.Now.ToString("dd_MM_yyyy_HH_mm_ss")Guid.NewGuid().ToString() 函数,以创建适当的已处理文件名,而无需冒任何异常的风险。

因为这是一个控制台应用程序,我使用了 Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)。 但是,在 Windows Forms 中,您可以使用 Application.StartupPath 代替。

历史

  • 2007年10月27日 - 发布第一个版本。
© . All rights reserved.