c#FileStream Read与StreamReader EndOfStream存在问题
正如标题所说,我发现了一个问题。首先是小背景故事: 我们的c#FileStream Read与StreamReader EndOfStream存在问题,c#,filestream,streamreader,C#,Filestream,Streamreader,正如标题所说,我发现了一个问题。首先是小背景故事: 我们的file.txt如下所示: aaaabb ccccddd eeeefffffff 逐行阅读此文本有多种方法,其中之一是: StreamReader sr = new StreamReader("file.txt"); while(!sr.EndOfStream) { string s = sr.ReadLine(); } sr.Close(); 工作s获取每一行。 现在我需要前4个字母作为字节,其余的作为字符串。在查找资料并进
file.txt
如下所示:
aaaabb
ccccddd
eeeefffffff
逐行阅读此文本有多种方法,其中之一是:
StreamReader sr = new StreamReader("file.txt");
while(!sr.EndOfStream)
{
string s = sr.ReadLine();
}
sr.Close();
工作s
获取每一行。
现在我需要前4个字母作为字节,其余的作为字符串。在查找资料并进行一点实验后,我发现最简单的方法是:
FileStream fs = new FileStream("file.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
byte[] arr = new byte[4];
fs.Read(arr, 0, 4);
string s = sr.ReadLine();
sr.Close();
fs.Close();
工作arr
包含前4个字母作为字节,行的其余部分保存在s
中。这只是一行。如果我们在添加的同时添加:
FileStream fs = new FileStream("file.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
while(!sr.EndOfStream)
{
byte[] arr = new byte[4];
fs.Read(arr, 0, 4);
string s = sr.ReadLine();
}
sr.Close();
fs.Close();
现在有个问题了。现在,arr
没有得到任何信息,s
读取整行内容,包括前4个字母。更奇怪的是,如果我使用while(true)
(我假设其他任何不是示例的东西)而不是预期的效果,那么4个字符作为字节,其余的是字符串,这对每一行都是一样的
问题是我错过了什么?为什么会这样?我如何解决这个问题?或者这可能是一个bug吗?这里的问题是简单的缓冲。将StreamReader
附加到FileStream
时,它会消耗文件中的一个块,从而提升FileStream
的当前位置。使用示例文件和默认缓冲区大小,一旦StreamReader
连接自身,它基本上会将整个文件消耗到缓冲区中,使FileStream
处于其EOF。然后,当您试图通过fs
引用直接从FileStream
中读取4个字节时,就没有什么可消耗的了。以下ReadLine
适用于从缓冲文件内容读取的sr
引用
下面是正在发生的事情的逐步细分:
fs
打开文件并位于位置
0
sr
将fs
打包,对EndOfStream
的调用(在本例中)将27个字节消耗到其内部缓冲区中。此时,fs
位置现在位于EOF
您试图直接从fs
读取,但它在EOF时没有更多字节
sr.ReadLine
从它在步骤2中建立的缓冲区中读取数据,所有这些都工作正常
要修复特定的错误情况,可以将字节数组更改为字符数组,并改用sr.Read
。i、 e
char[] arr = new char[4];
sr.Read(arr, 0, 4);
现在有个问题了。现在,arr什么也没有得到,s读整行,包括前4个字母
是的,这似乎很有道理StreamReader
维护一个缓冲区—当您要求它读取一行文本时,它很可能会从流中读取比那一行更多的内容,在下次要求它提供信息时使用缓冲数据
基本上,我强烈建议不要直接从StreamReader
正在读取的流中读取。即使在可能的情况下,也很难做到正确,在某些情况下,API可能不允许您做您想做的事情
如果要从每行中删除前四个字符,则更简单的方法是读取整行,然后使用Substring
从fs
中读取数组,然后从sr
中读取其余行。谢谢。我只想说,这似乎是因为这种消费只发生在sr使用或类似的东西。这就是为什么在sr初始化时,仍然可以使用fs.Read(),但在sr.ReadLine()或sr.EndOfStream之后,fs.Read()将停止给出结果。也是的,我删除了它,因为我做了一些错误的测试,并假设了错误的事实。所以为了不保留虚假信息,我决定删除它。