C# 中同时读写文件
我有一个包含数据的文件,我想监视这些数据的更改,并添加我自己的更改。像“Tail -f foo.txt”一样思考。
基于这个线程,看起来我应该创建文件流,并将其传递给写入器和读取器。然而,当读者到达原始文件的末尾时,它看不到我自己编写的更新。
我知道这看起来很奇怪……这更像是一个实验,看看是否可以做到。
这是我尝试过的示例:
foo.txt:
一个
b
c
d
电子
f
string test = "foo.txt";
System.IO.FileStream fs = new System.IO.FileStream(test, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);
var sw = new System.IO.StreamWriter(fs);
var sr = new System.IO.StreamReader(fs);
var res = sr.ReadLine();
res = sr.ReadLine();
sw.WriteLine("g");
sw.Flush();
res = sr.ReadLine();
res = sr.ReadLine();
sw.WriteLine("h");
sw.Flush();
sw.WriteLine("i");
sw.Flush();
sw.WriteLine("j");
sw.Flush();
sw.WriteLine("k");
sw.Flush();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
经过“f”后,读取器返回 null。
I have a file containing data that I'd like to monitor changes to, as well as add changes of my own. Think like "Tail -f foo.txt".
Based on this thread, it looks like I should just create a filestream, and pass it both to a writer and reader. However, when the reader reaches the end of the original file, it fails to see updates I write myself.
I know it seems like a weird situation... its more an experiment to see if it can be done.
Here is the example case I tried:
foo.txt:
a
b
c
d
e
f
string test = "foo.txt";
System.IO.FileStream fs = new System.IO.FileStream(test, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);
var sw = new System.IO.StreamWriter(fs);
var sr = new System.IO.StreamReader(fs);
var res = sr.ReadLine();
res = sr.ReadLine();
sw.WriteLine("g");
sw.Flush();
res = sr.ReadLine();
res = sr.ReadLine();
sw.WriteLine("h");
sw.Flush();
sw.WriteLine("i");
sw.Flush();
sw.WriteLine("j");
sw.Flush();
sw.WriteLine("k");
sw.Flush();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
res = sr.ReadLine();
After getting past "f", the reader returns null.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好的,稍后进行两次编辑...
这应该可行。我第一次尝试时,我想我忘记了在 oStream 上设置 FileMode.Append。
Ok, two edits later...
This should work. The first time I tried it I think I had forgotten to set FileMode.Append on the oStream.
@mikerobi 是正确的,当您写入流时,文件指针会更改并移动到流的末尾。您不指望的是 StreamReader 有自己的缓冲区。它从文件中读取 1024 个字节,您将从该缓冲区中获得结果。直到缓冲区用完,所以它必须再次从 FileStream 中读取。什么也没找到,因为文件指针位于文件末尾。
您确实需要分离 FileStream,每个 FileStream 都有自己的文件指针才能实现此目的。
@mikerobi is correct, when you write to the stream the file pointer is changed and moved to the end of the stream. What you are not counting on is that StreamReader has its own buffer. It reads 1024 bytes from the file and you'll get results from that buffer. Until the buffer runs out so it has to read from the FileStream again. Finding nothing because the file pointer is at the end of the file.
You really do need to separate FileStreams, each with their own file pointer to have any hope of making this work.
我相信每次写入一个字符时,您都会推进流位置,因此下一次读取会尝试在刚刚写入的字符之后读取。发生这种情况是因为您的流读取器和流写入器使用相同的 FileStream。使用不同的文件流,或在每次写入后在流中寻找 -1 个字符。
I believe that every time you write a character, you are advancing the stream position, so the next read attempts to read after the character you just wrote. This happens because your stream reader and stream writer are using the same FileStream. Use a different filestream, or seek -1 characters back in the stream after every write.
您不太可能对涉及使用相同流进行读取和写入的此问题的任何解决方案感到满意。如果您尝试使用 StreamReader 读取文件的尾部,则尤其如此。
您想要有两个不同的文件流。如果您愿意,写入流可以是 StreamWriter。读取流应该是二进制流(即使用
File.OpenRead
或FileStream.Create
创建),从文件中读取原始字节,然后转换为文本。我对这个问题的回答显示了它是如何完成的基础知识。It's highly unlikely that you'd be happy with any solution to this problem that involves using the same stream for reading and writing. That's especially true if you're trying to read the tail of the file using a
StreamReader
.You want to have two different file streams. The writing stream can be a
StreamWriter
if you like. The reading stream should be a binary stream (i.e. create withFile.OpenRead
orFileStream.Create
), read raw bytes from the file, and convert to text. My answer to this question shows the basics of how it's done.