正如标题所说,我发现了一个问题。小故事第一:
我们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
中。这只是一行。如果我们添加while
:
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个字符作为字节,其余为字符串,这对于每一行都是相同的。
问题是我错过了什么?为什么会这样?我该如何解决这个问题?或者这可能是一个错误?
答案 0 :(得分:7)
这里的问题是简单的缓冲。当您将StreamReader
附加到FileStream
时,它最终会占用文件中的一个块,从而推进Position
的当前FileStream
。使用您的示例文件和默认缓冲区大小,一旦StreamReader
附加自身,它基本上将整个文件消耗到缓冲区中,使FileStream
保持在其EOF。当您尝试直接通过FileStream
引用从fs
读取4个字节时,没有什么可以消耗的。以下ReadLine
适用于sr
引用,因为它是从缓冲文件内容中读取的。
以下是对正在发生的事情的逐步细分:
fs
打开文件并位于Position
0。sr
包裹fs
,对EndOfStream
的调用最终消耗(在本例中)27个字节到其内部缓冲区。此时,fs
Position
现在位于EOF。fs
读取,但在EOF中没有更多字节。sr.ReadLine
从步骤#2中构建的缓冲区中读取,一切正常。要修复特定的错误情况,可以将字节数组更改为char数组,然后使用sr.Read
。即。
char[] arr = new char[4];
sr.Read(arr, 0, 4);
答案 1 :(得分:4)
现在出现了问题。现在arr并没有得到任何东西,并且s读取整行,包括前4个字母。
是的,这似乎很合理。 StreamReader
维护一个缓冲区 - 当你要求它读取一行文本时,它可能会从流中读取 more 而不是单行,使用缓冲后的数据接下来要求提供信息。
从根本上说,我强烈建议直接从流中读取StreamReader
正在读取的内容。即使在可能的情况下,它也会变得非常繁琐,在某些情况下,API可能不会让你做你想做的事。
如果你想从每一行中删除前四个字符,那么读取整行就会 更简单,然后使用Substring
。