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)
...
【讨论】:
请注意,Position
和 Length
是 Stream
类的属性,而不是方法。除非您定义了具有相同名称的扩展方法,否则方法调用语法将无法编译。
谢谢,我不知道为什么我以前把它们写成方法。
这仅在底层 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# 中使用 QDataStream 读取在 QT 中创建的二进制文件
将二进制文件读取(fread)代码从 MATLAB 转换为 C#