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

Posted

技术标签:

【中文标题】C# 检查文件的二进制读取器结尾【英文标题】:C# checking for binary reader end of file 【发布时间】:2012-06-12 03:48:53 【问题描述】:

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

while (inFile.PeekChar() > 0)

    ...

不过,我好像遇到了问题

未处理的异常:System.ArgumentException:输出字符缓冲区太小 ll 包含解码后的字符,编码 'Unicode (UTF-8)' fallback 'Syste m.Text.DecoderReplacementFallback'。 参数名称:字符 在 System.Text.Encoding.ThrowCharsOverflow() 在 System.Text.Encoding.ThrowCharsOverflow(DecoderNLS 解码器,布尔无 g解码) 在 System.Text.UTF8Encoding.GetChars(Byte* 字节,Int32 byteCount,Char* char s, Int32 charCount, DecoderNLS baseDecoder) 在 System.Text.DecoderNLS.GetChars(Byte* bytes, Int32 byteCount, Char* chars, Int32 charCount,布尔刷新) 在 System.Text.DecoderNLS.GetChars(Byte[] bytes, Int32 byteIndex, Int32 byteC ount,Char[] 字符,Int32 charIndex,布尔刷新) 在 System.Text.DecoderNLS.GetChars(Byte[] bytes, Int32 byteIndex, Int32 byteC 数量,Char[] 字符,Int32 字符索引) 在 System.IO.BinaryReader.InternalReadOneChar() 在 System.IO.BinaryReader.PeekChar()

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

【问题讨论】:

使用 StreamReader(字符流)读取文本文件。如果您想读取文件,我建议 BinaryReader.ReadBytes(nBytes_to_be_read)。 根据您的具体代码和文件访问是否共享,您也许还可以将流的 .Length 属性缓存到局部变量,这将进一步优化和提高性能。跨度> 【参考方案1】:

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

while (inFile.BaseStream.Position != inFile.BaseStream.Length)

   ...

【讨论】:

请注意,PositionLengthStream 类的属性,而不是方法。除非您定义了具有相同名称的扩展方法,否则方法调用语法将无法编译。 谢谢,我不知道为什么我以前把它们写成方法。 这仅在底层 Stream 支持查找时才有效。 @Paul PeekChar 也是如此,所以这并没有什么区别 :) 根据底层流,调用BaseStream.Length 可能真的很慢。 FileStream 例如,每次都会调用Win32.GetFileSize()。如果你知道长度不会改变,你可能想先缓存它(例如:在本地变量中)【参考方案2】:

将其包装到 Custom Extension Method 中,这将通过添加缺少的 EOF 方法来扩展 BinaryReader 类。

public static class StreamEOF 

    public static bool EOF( this BinaryReader binaryReader ) 
        var bs = binaryReader.BaseStream;
        return ( bs.Position == bs.Length);
    

所以现在你可以写:

while (!infile.EOF()) 
   // Read....

:) ...假设您在这样的地方创建了 infile

var infile= new BinaryReader();

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

【讨论】:

错了,大错特错。应该返回(bs.Position == bs.Length);和 !infile.EOF()【参考方案3】:

这对我有用:

using (BinaryReader br = new BinaryReader(File.Open(fileName,   
FileMode.Open))) 
            //int pos = 0;
            //int length = (int)br.BaseStream.Length;
            while (br.BaseStream.Position != br.BaseStream.Length) 
                string nume = br.ReadString ();
                string prenume = br.ReadString ();
                Persoana p = new Persoana (nume, prenume);
                myArrayList.Add (p);
                Console.WriteLine ("ADAUGAT XXX: "+ p.ToString());
                //pos++;
            
        

【讨论】:

【参考方案4】:

我建议与@MxLDevs 非常相似,但使用'

while (inFile.BaseStream.Position < inFile.BaseStream.Length)

   ...

【讨论】:

【参考方案5】:

我将添加我的建议:如果您不需要 BinaryReader 的“编码”部分(因此您不使用各种 ReadChar/ReadChars/ReadString),那么您可以使用永远不会的编码器throw 并且总是每个字符一个字节。 Encoding.GetEncoding("iso-8859-1") 非常适合这个。您将它作为BinaryReader 构造函数的参数传递。 iso-8859-1 编码是每个字符一个字节的编码,它以 1:1 的比例映射 Unicode 的所有前 256 个字符(例如,byte 254 是 char 254)

【讨论】:

其中一个 cmets 解决了不支持搜索的流不支持直接检查流长度的问题。我想这可能会在这种情况下解决这个问题。 @MxyL 不,它不会解决那个问题。 PeekChar() 执行Read(),然后使用Position 回滚Read() 为了清楚起见,使用特定编码检查文件末尾的建议方法是什么?

以上是关于C# 检查文件的二进制读取器结尾的主要内容,如果未能解决你的问题,请参考以下文章

请教c#读取二进制文件的问题

在 C# 中使用 QDataStream 读取在 QT 中创建的二进制文件

将二进制文件读取(fread)代码从 MATLAB 转换为 C#

我可以使用 C# 序列化来读取自定义格式的二进制文件吗?

python读取C#写的二进制文件,byte类型unpack

C# 读写二进制文件