C# 在写入文件后立即读取该文件,我得到所有零(.net)

C# 在写入文件后立即读取该文件,我得到所有零(.net),c#,.net,file-io,file-locking,C#,.net,File Io,File Locking,我有一个程序,需要从一个目录加载文件,一旦他们被写入。我让FileSystemWatcher通知我目录的更改。我没有检查事件中发生了什么变化,而是列出了文件并开始处理我发现的所有内容 为了防止试图读取仍在编写的文件,我有如下代码: try { fs = fi.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); message = new byte[fs.Length];

我有一个程序,需要从一个目录加载文件,一旦他们被写入。我让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个文件中就有1个文件,程序读取的是全零。文件长度正确,但内容似乎都是零字节。当我检查后一个文件时,我发现它确实包含正确的数据。我认为我打开文件的方式可以防止过早访问该文件

我通过将文件复制到目录中,使用DOS命令“复制IfFiele0*DROPDIR”(每执行大约100个文件)。这个命令可能在两个步骤中执行复制:1)分配空间,2)填充空间,而我的程序偶尔在中间跳跃。

关于如何将其编码为可靠的,有什么想法吗


更新:我无法控制编写程序-它可能是任何东西。看起来我必须进行防御性编码。

您遇到了比赛条件。除非您最终修复它,否则情况只会变得更糟(使用网络文件系统等)

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

或者,在目录中保留一个名为“sentinel”或类似文件的零长度文件。每次成功写入另一个文件后,让程序写入文件以重写sentinel文件。然后,不要尝试读取修改日期/时间大于等于sentinel文件修改日期/时间的文件

或者,如果您无法控制文件的编写者,请对照当前系统日期/时间检查每个文件的修改日期/时间。在尝试读取文件之前,让文件老化适当的时间(如果文件较小,则几秒钟;如果文件较大,则更长)


祝你好运。这是一个臭名昭著的颈部疼痛。

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

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

我认为你应该更仔细地审视作者的行为。并尝试使用只读、共享所有访问来减少对文件访问的干扰:

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

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

提示:为异常添加日志记录。不要默默地失败。您使用的程序不会对文件设置任何锁。例如,fopen()对于C程序来说很常见,它允许任何程序在打开文件时读写。除了“等待一段时间”之外,没有太多方法可以获胜。我最初确实打开了它FileAccess。读过之后,零文件也有同样的问题。打开.ReadWrite是为了解决这个问题-我认为请求写访问权限可能会延迟我对文件的访问,直到所有写入程序都实际完成它。我不知道FileShare.ReadWrite如何解决这个问题。它比没有更宽容,我需要更少的宽容。另外,文件上写着“后续开业”——我之后的流程。我在作者之后,所以我希望作者在开始时使用。无。但我无法控制这一切。当然,我可能错误地解释了文档,或者文档可能是错误的。