从C#中正在增长的文件中读取?

在C#/ .net(在Windows上)有没有办法使用文件stream来读取“增长”的文件? 当文件stream被打开时,文件的长度会很小,但是文件将被另一个线程写入。 如果/当文件stream“追上”到另一个线程(即,当Read()返回0字节读取),我想暂停以允许文件缓冲一下,然后继续阅读。

我真的不想使用FilesystemWatcher并不断创build新的文件stream(正如为日志文件所build议的那样),因为这不是一个日志文件(这是一个正在编码的video文件),性能是一个问题。

谢谢,
罗伯特

Solutions Collecting From Web of "从C#中正在增长的文件中读取?"

你可以这样做,但是你需要使用Stream.Seek来仔细跟踪文件的读写位置,并且在线程之间进行适当的同步。 通常情况下,您可以使用EventWaitHandle或其子类来执行数据同步,并且还需要考虑同步访问FileStream对象本身(可能通过lock语句)。

更新:在回答这个问题时,我实现了类似的东西 – 一个文件在后台下载并同时上传的情况。 我使用了内存缓冲区,并发布了具有工作代码的要点 。 (这是GPL,但对你来说可能并不重要 – 无论如何,你可以用这些原则来做你自己的事情。)

我解决这个问题的方法是使用DirectoryWatcher / FilesystemWatcher类,当它触发文件时,您需要打开一个FileStream并将其读取到最后。 当我完成阅读时,我保存阅读器的位置,所以下次DirectoryWatcher / FilesystemWatcher触发我打开一个流设置的位置,我上次在哪里。

调用FileStream.length实际上非常慢,我没有性能问题与我的解决方案(我正在阅读一个“日志”范围从10MB到50 ish)。

对我来说,我描述的解决方案是非常简单和容易维护,我会尝试它,并配置文件。 我不认为你会得到任何性能问题的基础上。 我这样做是因为在玩多线程游戏的时候,他们拿着整个CPU,而没有人抱怨说我的解析器对竞争解析器的要求更高。

这与一个文件周围的StreamReader一起工作,具有以下步骤:

  1. 在写入文件的程序中,使用读共享打开它,如下所示:

     var out = new StreamWriter(File.Open("logFile.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)); 
  2. 在读取文件的程序中,使用读写共享打开它,如下所示:

     using (FileStream fileStream = File.Open("logFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using ( var file = new StreamReader(fileStream)) 
  3. 在访问输入流之前,检查是否已到达输入流,如果是,请稍等片刻。

     while (file.EndOfStream) { Thread.Sleep(5); } 

另一个可能有用的事情是FileStream类有一个名为ReadTimeOut的属性,它被定义为:

获取或设置一个值(以毫秒为单位),该值确定在超时之前流将尝试读取多长时间。 (从Stream继承)

这可能是有用的,当你的读取赶上你的写入执行读取的线程可能会暂停写入缓冲区刷新。 这是值得写一个小测试,看看这个属性是否会以任何方式帮助你的事业。

读写操作是否发生在同一个对象上? 如果是这样,你可以写自己的文件的抽象,然后编写交叉线程通信代码,使正在执行写入的线程,并通知执行读取的线程,以便执行读取的线程知道何时停止阅读当它到达EOF。