自动处理传入文件






2.18/5 (13投票s)
使用 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日 - 发布第一个版本。