C#检查二进制阅读器文件结尾

MxL*_*evs 42 c# binaryfiles binaryreader

我正在寻找一种方法来检查我是否已经到达我的二进制阅读器的文件的末尾,并且一个建议是使用PeekChar这样

while (inFile.PeekChar() > 0)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是,看起来我遇到了一个问题

Unhandled Exception: System.ArgumentException: The output char buffer is too sma
ll to contain the decoded characters, encoding 'Unicode (UTF-8)' fallback 'Syste
m.Text.DecoderReplacementFallback'.
Parameter name: chars
   at System.Text.Encoding.ThrowCharsOverflow()
   at System.Text.Encoding.ThrowCharsOverflow(DecoderNLS decoder, Boolean nothin
gDecoded)
   at System.Text.UTF8Encoding.GetChars(Byte* bytes, Int32 byteCount, Char* char
s, Int32 charCount, DecoderNLS baseDecoder)
   at System.Text.DecoderNLS.GetChars(Byte* bytes, Int32 byteCount, Char* chars,
 Int32 charCount, Boolean flush)
   at System.Text.DecoderNLS.GetChars(Byte[] bytes, Int32 byteIndex, Int32 byteC
ount, Char[] chars, Int32 charIndex, Boolean flush)
   at System.Text.DecoderNLS.GetChars(Byte[] bytes, Int32 byteIndex, Int32 byteC
ount, Char[] chars, Int32 charIndex)
   at System.IO.BinaryReader.InternalReadOneChar()
   at System.IO.BinaryReader.PeekChar()

所以也许PeekChar不是最好的方法,我认为它甚至不应该以这种方式使用,因为我正在检查读者的当前位置,而不是下一个字符应该是什么.

MxL*_*evs 82

在处理二进制数据时,有一种更准确的方法来检查EOF.它避免了该PeekChar方法带来的所有编码问题并完全满足需要:检查读取器的位置是否位于文件的末尾.

while (inFile.BaseStream.Position != inFile.BaseStream.Length)
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

  • 这仅在基础流支持搜索时有效. (13认同)
  • 请注意,`Position` 和`Length` 是`Stream` 类的属性,而不是方法。除非您定义了具有相同名称的扩展方法,否则方法调用语法将无法编译。 (3认同)
  • 根据底层流的不同,调用“BaseStream.Length”可能会非常慢。例如,“FileStream”每次都会调用“Win32.GetFileSize()”。如果您知道长度不会改变,您可能需要先缓存它(例如:在本地变量中) (3认同)
  • 谢谢,我不知道为什么我以前把它们写成方法。 (2认同)
  • @Paul So`PeekChar`,所以这不是真正的区别:) (2认同)

Tin*_*oon 8

我建议与 @MxLDevs 非常相似,但使用“<”运算符而不是“!=”运算符。由于可以将 Position 设置为您想要的任何值(在长范围内),这将阻止任何通过循环访问无效文件 Position 的尝试。

while (inFile.BaseStream.Position < inFile.BaseStream.Length)
{
   ...
}
Run Code Online (Sandbox Code Playgroud)


Un *_*Peu 5

将其包装到自定义扩展方法中,该方法将通过添加缺少的 EOF 方法来扩展BinaryReader类。

public static class StreamEOF {

    public static bool EOF( this BinaryReader binaryReader ) {
        var bs = binaryReader.BaseStream;
        return ( bs.Position == bs.Length);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在你可以写:

while (!infile.EOF()) {
   // Read....
}
Run Code Online (Sandbox Code Playgroud)

:) ...假设你已经在这样的地方创建了infile

var infile= new BinaryReader();
Run Code Online (Sandbox Code Playgroud)

注意:var是隐式类型。很高兴找到它 - 它是 C# 中风格良好的代码的另一个拼图。:D

  • 错,非常错。应该是 return ( bs.Position == bs.Length); 和 !infile.EOF() (2认同)