在写完文件之后立即读取文件我得到全零(.net)

时间:2011-01-20 00:00:19

标签: c# .net file-io file-locking

我有一个程序需要在编写后立即从目录加载文件。我得到了FileSystemWatcher来通知我目录的更改。而不是检查事件的变化,我只列出文件并开始处理我发现的所有内容。

为防止尝试读取仍在写入的文件,我的代码如下:

try {
    fs = fi.Open(FileMode.Open, FileAccess.ReadWrite,
                    FileShare.None);
    message = new byte[fs.Length];
    int br = fs.Read(message, 0, (int)fi.Length);
}
catch (Exception e) {
    // I'll get it next time around
    return;
}
finally {
    if (fs != null)
        fs.Close();
}

问题是,对于某些文件,大约每200个文件中,该程序读取全零。文件长度正确但内容似乎都是零字节。当我检查文件后,我发现它确实包含实际的正确数据。我认为打开文件的方式会阻止过早访问文件。

我正在使用DOS命令'copy InFile_0 * dropdir'(每次执行大约100个文件)将文件复制到目录来测试这个。可能这个命令分两步完成复制:1)分配空间和2)填充空间和我的程序偶尔跳到两个中间。

关于如何对此进行编码以使其可靠的任何想法?

更新:我无法控制写作程序 - 它可能是任何东西。看起来我必须采取防御措施。

2 个答案:

答案 0 :(得分:2)

你正在遇到竞争条件。除非你明确地修复它,否则它将从这里变得更糟(使用网络文件系统等)。

尝试让编写文件的程序使用“whatever.tmp”名称写入每个文件,然后将其关闭,然后重命名。阅读时,请忽略.tmp文件。

或者,在目录中保留一个名为“sentinel”的零长度文件或其他文件。获取编写文件的程序,以便在每次成功写入另一个文件后重写sentinel文件。然后,不要尝试读取修改日期/时间>> = sentinel文件的修改日期/时间的文件。

或者,如果您无法控制文件的编写者,请根据当前系统日期/时间检查每个文件的修改日期/时间。在尝试阅读之前,让文件老化适当的数量(如果它们较小则为几秒,如果它们较大则为较长)。

祝你好运。这是一个臭名昭着的痛苦。

答案 1 :(得分:1)

好吧,我不同意@Ollie Jones以前的帖子。

您已经建立了对该文件的独占访问权限,因此没有竞争条件问题。

我认为你应该更仔细地检查一下作家的行为。并尝试通过只读减少对文件访问的干扰,共享所有访问权限:

fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

这可能会使您的读取失败但会减少写入错误。要确定何时安全阅读,您可以检查文件时间或文件大小或其他。如果随后将写入许多文件,您可以在创建第二个文件后开始读取第一个文件。