C# BinaryReader 结束流

C# BinaryReader end of Stream

我想知道使用 EndOfStreamException 来检测 BinaryReader 流的结尾是否是一个好习惯>我不想使用 BaseStream.Length 属性 或此处建议的 PeekChar

C# checking for binary reader end of file

因为我必须将它加载到内存中(可能是因为它来自 Zip 文件)并启用一些标志。相反,这就是我正在做的:

using (ZipArchive zipArchive = ZipFile.OpenRead(Filename))
  using (BinaryReader fStream = new BinaryReader(zipArchive.Entries[0].Open()))
  {
    while(true){
    try
    {
      fStream.ReadInt32();
    }
    catch (EndOfStreamException ex)
    {
      Log.Debug("End of Binary Stream");
      break;
    }
}

}

这种方法很好。如果你知道你有一个可搜索的流,你可以将它的长度与读取的字节数进行比较。请注意 FileStream.Length 不会将整个流加载到内存中。

但这种方法适用于任意流。

并且不必担心在这种情况下使用异常的成本,因为流意味着 IO,而 IO 比异常处理慢几个数量级。

我认为 'best practice' 是为了让值的数量已知,例如通过在流前加上值的数量作为前缀。这应该允许你这样写

var length = fStream.ReadInt32();
for(var i = 0; i < length-1; i++){
    fStream.ReadInt32(); // Skip all values except last
}
return fStream.ReadInt32(); // Last value

首先,这将减少异常处理的需要,如果您在最后一个项目之前到达 endOfStream,您知道流被错误保存,并且有机会处理它,而不是仅仅返回最后一个可用值.我还发现异常越少越好,因此您可以 运行 您的调试器使用“break with thrown”,并确信抛出的异常表明存在实际问题。它还可以让您将您的值保存为其他一些数据的一部分。

如果您无法更改输入格式,您仍然可以从 ZipArchiveEntry.Length 中获取条目的未压缩长度。只需除以 sizeof(int) 即可得到值的数量。

在大多数情况下,我也赞成使用序列化库来保存数据。这往往会使将来更改数据格式变得更加容易。

检查您的程序或初始值。