使用 EndOfStream 属性后出现 StreamReader.BaseStream 问题
本文关键字:StreamReader BaseStream 问题 EndOfStream 属性 使用 | 更新日期: 2023-09-27 18:36:25
首先,我知道我可以使用不同的方式解决此问题。我想这个问题的存在只是因为以不正确的方式使用了不同的方法。但我想找出我的例子中到底发生了什么。
我正在使用StreamReader来读取文件。为了从中获取字节,我决定使用BaseStream.Read:
int length = (int)reader.BaseStream.Length;
byte[] file = new byte[length];
while(!reader.EndOfStream)
{
int readBytes = reader.BaseStream.Read(file, 0,
(length-offset)>bufferSize?bufferSize:(length - offset));
for (int i = 0; i<readBytes; i++)
{
...
}
offset += readBytes;
}
BaseStream.Read 拒绝获取最后 1024 个字节,因为在读取之前使用了属性 StreamReader.EndOfStream。后来我发现了一个信息,EndOfStream 试图读取 1 个字节,但实际上由于性能,他读取了 1024 个字节。显然,这个 1kb 变得无法到达。
编辑:如果我删除阅读器。代码中的 EndOfStream 属性,读取器。BaseStream.Read 将正常工作。这是问题的主要问题。
同样,我知道,这个代码示例绝对是低效的。我只是想了解流在该示例中的工作原理,以及此问题是否仅因为错误代码而存在(或 StreamReader.BaseStream 有一些问题)?提前谢谢。
它不是StreamReader.BaseStream
有一些问题,而是你的代码中的问题。当您直接使用包裹在StreamReader
内的Stream
工作时。
来自 MSDN 关于 StreamReader.DiscardBufferedData:
仅当内部缓冲区和 BaseStream 的位置不匹配时,才需要调用此方法。当您将数据读入缓冲区,然后在基础流中查找新位置时,这些位置可能会不匹配。
这意味着,在您的情况下,当Stream
已经到达结束位置时,内部缓冲区的位置仍然是您直接读取基础流之前StreamReader
值,因此reader.EndOfStream
仍然 = false
。这就是为什么您无法完成循环的原因。
编辑:
我认为您缺少一些东西,我给您此代码以证明该文件已成功到达最后。运行它,你会看到你的应用程序反复说:我在文件的末尾!
static void Main()
{
using (StreamReader reader = new StreamReader(@"yourFile"))
{
int offset = 0;
int bufferSize = 102400;
int length = (int)reader.BaseStream.Length;
byte[] file = new byte[length];
while (!reader.EndOfStream)
{
// Add this line:
Console.WriteLine(reader.BaseStream.Position);
Console.ReadLine();
int readBytes = reader.BaseStream.Read(file, 0,
(length - offset) > bufferSize ? bufferSize : (length - offset));
string str = Encoding.UTF8.GetString(file, 0, readBytes);
offset += readBytes;
if (reader.BaseStream.Position == length)
{
Console.WriteLine("I'm at the end of the file! Current Tickcount: " + Environment.TickCount);
Thread.Sleep(100);
}
}
}
}
编辑 2
但是,偏移量和长度仍然应该相等,我的情况长度 - offset = 1024(如果文件大于 1kb)。也许我做错了什么,但是如果我使用大小小于 1kb 的文件,readBytes 总是等于 0。
那因为你第一次调用while (!reader.EndOfStream)
,读卡器必须读取文件(在这种情况下是1024字节 - 将字节读取到内部缓冲区)以确定文件是否结束(请参阅我上面添加的两行代码),在它读取文件后寻找1024字节,那为什么length - offset = 1024
,如果你的文件小于1kb,那么第一次调用, 它已经寻求文件结束。这是您丢失数据的地方。
不寻求,因为你没有向读取器发送任何读取请求,所以它认为不变,那么它就不需要再次读取文件来检查文件末尾是否,为什么第二次调用不会丢失数据。