在C#/ .NET中(在Windows上)有没有办法使用文件流来读取“增长”文件?当文件流被打开时,文件的长度会很小,但是文件将被另一个线程写入。如果/当文件流“追上”到另一个线程(即当Read()
返回0字节读取)时,我想暂停以允许文件缓冲一点,然后继续读取。从C#中增长的文件中读取?
我真的不想使用FilesystemWatcher
并继续创建新的文件流(正如对日志文件建议的那样),因为这不是日志文件(它是一个正在编码的视频文件)和性能是一个问题。
感谢,
罗伯特
在C#/ .NET中(在Windows上)有没有办法使用文件流来读取“增长”文件?当文件流被打开时,文件的长度会很小,但是文件将被另一个线程写入。如果/当文件流“追上”到另一个线程(即当Read()
返回0字节读取)时,我想暂停以允许文件缓冲一点,然后继续读取。从C#中增长的文件中读取?
我真的不想使用FilesystemWatcher
并继续创建新的文件流(正如对日志文件建议的那样),因为这不是日志文件(它是一个正在编码的视频文件)和性能是一个问题。
感谢,
罗伯特
您可以这样做,但需要使用Stream.Seek
以及线程之间的适当同步来仔细跟踪文件读取和写入位置。通常,您可以使用EventWaitHandle
或其子类进行数据同步,并且还需要考虑同步访问FileStream
对象本身(可能通过lock
语句)。
更新:在回答this question我实现了类似的东西 - 一个文件在后台下载并同时上传的情况。我用内存缓冲区,并发布了一个gist其中有工作代码。 (这是GPL,但对你来说可能并不重要 - 无论如何你可以使用这些原则来做你自己的事情。)
我会研究这个...对于踢腿,将编码结果写入内存(例如使用双缓冲区),然后将它同时发送到网络和缓存文件可能更容易吗? – 2009-09-11 07:53:22
我解决了这个使用DirectoryWatcher/FileSystemWatcher类,而当它触发的文件你想打开一个FileStream并读到尾的方式。当我完成阅读时,我保存了阅读器的位置,所以下次启动时,我打开一个流,将位置设置为我上次所在的位置。
调用FileStream.length实际上非常慢,我没有性能问题与我的解决方案(我正在读一个“日志”范围从10MB到50伊西)。
对我而言,我所描述的解决方案非常简单,易于维护,我会尝试并对其进行配置。我不认为你会基于它得到任何性能问题。当我玩这个多线程游戏时,我会这样做,并且不会有人抱怨我的解析器对竞争解析器的要求更高。
由于性能方面的考虑,该问题使用观察者特别打折。 – 2009-09-11 07:45:32
是的,我注意到了。在关于性能的回复中增加了更多内容。 – EKS 2009-09-11 07:46:04
如果您所做的只是尽可能读取,然后等待更多数据,则您不一定必须在读取器中调用FileStream.Length。你看到的观察者触发有什么样的延迟?这是否会根据机器负载而改变? – 2009-09-11 07:49:44
另一个可能有用的东西是FileStream类有一个名为ReadTimeOut的属性,它是定义为:
获取或设置一个值(以毫秒为单位),该值确定在超时之前流将尝试读取多长时间。 (继承自Stream)
这可能很有用,因为当您的读取赶上您的写入时,执行读取的线程在写入缓冲区被刷新时可能会暂停。这肯定是值得写一个小测试,看看这个属性是否会以任何方式帮助你的事业。
读写操作是否发生在同一个对象上?如果是这样,你可以在文件上编写自己的抽象,然后编写交叉线程通信代码,以便正在执行写入的线程通知执行读取的线程,以便执行读取的线程知道何时停止读取当它达到EOF时。
如果在FileStream上设置ReadTimeOut会引发异常,该如何得到+3? :S – 2015-12-24 22:50:13
这大约有文件一个StreamReader工作,具有以下步骤:
在写入到文件的程序,以读取共享打开它,像这样:
var out = new StreamWriter(File.Open("logFile.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read));
在读取文件的程序中,使用读写共享打开它,如下所示:
using (FileStream fileStream = File.Open("logFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var file = new StreamReader(fileStream))
访问输入流之前,请检查是否已到达输入流,如果有,请稍等片刻。
while (file.EndOfStream)
{
Thread.Sleep(5);
}
我更新了我的答案。 – 2009-09-11 08:10:37