BinaryWriter写入需调用Flush()或Close()确保落盘,推荐using自动释放;BinaryReader.ReadString()依赖BinaryWriter写入的长度前缀和UTF-8编码;结构体须逐字段手动序列化;EOF判断应依赖长度头而非PeekChar()或Position比较。
BinaryWriter写入二进制文件时,必须手动调用
或
才能确保数据落盘
很多人写完
就以为文件已保存,结果打开全是空的或缺尾部数据。这是因为
内部有缓冲区,默认不会每写一次就刷到磁盘。
推荐用
语句自动释放和刷新:
如果不用
,务必在最后调用
(
也行),
只清缓冲区,不关闭流
直接写
绕过
?可以,但会丢失类型编码逻辑(比如
自动写长度前缀)
BinaryReader读取时,
依赖UTF-8编码且要求前缀长度,不是原始字节读取
不是读“直到\0”或“一行”,而是读一个7位编码的长度前缀(变长整数),再读对应字节数的UTF-8内容。如果文件不是用
写的,大概率抛
或乱码。
确认写入端:只有
写的数据,才能用
安全读
想读裸字节?改用
或
等基础方法
编码不匹配?
构造时可传
,但
仍按自己的格式解析长度——编码只影响后续UTF-8解码
结构体序列化不能直接用BinaryWriter,需手动拆解字段
没有
重载。它不理解结构体布局、字段顺序、对齐或
,直接
又容易踩平台差异(比如
占1字节还是4字节)。
C知道
CSDN推出的一款AI技术问答工具
下载
安全做法:逐字段写,控制顺序和大小
需要紧凑二进制?考虑
+
(.NET Core 3+),但得确保
是
且无引用类型
跨语言交互?别依赖
默认行为——它不保证与C/C++结构体二进制兼容
文件末尾判断别用
,
没有可靠的EOF探测方法
在二进制流上意义不大(它尝试按当前编码读字符,可能失败或误判);
看似合理,但在网络流或压缩流中不可靠。
正确做法:明确知道要读多少项,或用长度头控制
真要试探读?捕获
,但仅适用于“尽力而为”场景,不能作为主控逻辑
注意:
返回
表示EOF,但
等直接抛异常,行为不统一
实际用起来最常卡住的,是写入后没关流导致文件不完整,以及误把
当通用字符串读取器——它和写入端强绑定,换种方式写进去,就读不出来。
Flush()Close()Write()BinaryWriterusingusing (var fs = new FileStream("data.bin", FileMode.Create))
using (var writer = new BinaryWriter(fs))
{
writer.Write(42);
writer.Write("hello");
} // Close() 和 Flush() 在这里自动触发usingwriter.Close()Dispose()Flush()fs.Write()BinaryWriterstringReadString()BinaryReader.ReadString()BinaryWriter.WriteString()EndOfStreamExceptionBinaryWriter.WriteString()BinaryReader.ReadString()reader.ReadBytes(n)reader.ReadChar()BinaryReaderEncodingReadString()BinaryWriterWrite(MyStruct)[MarshalAs]Marshal.Copyboolwriter.Write(point.X); // double
writer.Write(point.Y); // double
writer.Write(point.IsActive); // bool → 写为 byte 0/1 更可控SpanUnsafe.AsstructblittableBinaryWriterPeekChar()BinaryReaderPeekChar()BaseStream.Position == BaseStream.Length// 写入时先写元素数量
writer.Write(items.Count);
foreach (var item in items) { ... }
// 读取时先读数量,再循环
int count = reader.ReadInt32();
for (int i = 0; i < count; i++) { ... }EndOfStreamExceptionReadByte()-1ReadInt32()ReadString()