-1

我有一个函数可以检查目录中的每个文件并将列表写入控制台。问题是,我不希望它包含当前正在复制到目录的文件,我只希望它显示完整的文件。我怎么做?这是我的代码:

foreach (string file in Directory.EnumerateFiles("C:\folder"))
        {
            Console.WriteLine(file);
        }
4

3 回答 3

3

真的没有办法区分“被复制”和“被某些东西锁定”。相关:如何检查文件锁定?我可以简单地“读取”正在使用的文件吗

如果您只想显示未打开以供写入的文件列表,您可以通过尝试打开它们来实现:

foreach (string file in Directory.EnumerateFiles("C:\folder"))
{
   try {
     using (var file = file.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) {
       Console.WriteLine(file);
     }
   } catch {
     // file is in use
     continue;
   }
}

但是 - 很多警告。

  • 显示文件名(using块的末尾)后,文件可以立即被其他东西打开
  • 写入文件的进程可能使用了 FileShare.Read,这意味着调用将成功,尽管它已被写入。

我不确定您到底在做什么,但这听起来像是两个进程共享一个队列目录:一个写入,一个读取/处理。最大的挑战是写入文件需要时间,因此您的“读取”过程最终会在整个文件存在之前将其拾取并尝试读取它,这会以某种方式失败,具体取决于共享模式,您的应用程序如何写的等等。

处理这种情况的常见模式是使用原子文件操作,例如Move

  • 对与队列目录位于同一文件系统(非常重要)上的临时目录执行(慢速)写入/复制操作
  • 完成后,从临时目录移动到队列目录。

由于 move 是原子的,因此文件要么不存在,要么 100% 存在——“读取”过程在文件部分存在时没有机会看到文件。

请注意,如果您跨文件系统进行移动,它将与副本相同。

于 2013-07-19T21:12:05.827 回答
1

Windows/.NET/whatever 中的任何位置都没有存储“当前正在复制的文件”列表。可能您最多可以尝试打开每个文件进行追加,看看是否有异常。根据目录的大小和位置以及安全设置,这可能不是一个选项。

于 2013-07-19T20:59:06.590 回答
1

没有一种干净的方法可以做到这一点,但这...有效...

foreach (var file in new DirectoryInfo(@"C:\Folder").GetFiles())
{
    try
    {
        file.OpenRead();
    }
    catch
    {
        continue;
    }
    Console.WriteLine(file.Name);
}
于 2013-07-19T21:01:21.423 回答