C#二进制文件读写 C#如何用BinaryReader和BinaryWriter

来源:这里教程网 时间:2026-02-21 17:42:09 作者:

BinaryWriter写入二进制文件时,必须手动调用
Flush()
Close()
才能确保数据落盘

很多人写完

Write()
就以为文件已保存,结果打开全是空的或缺尾部数据。这是因为
BinaryWriter
内部有缓冲区,默认不会每写一次就刷到磁盘。

推荐用
using
语句自动释放和刷新:
using (var fs = new FileStream("data.bin", FileMode.Create))
using (var writer = new BinaryWriter(fs))
{
    writer.Write(42);
    writer.Write("hello");
} // Close() 和 Flush() 在这里自动触发
如果不用
using
,务必在最后调用
writer.Close()
Dispose()
也行),
Flush()
只清缓冲区,不关闭流
直接写
fs.Write()
绕过
BinaryWriter
?可以,但会丢失类型编码逻辑(比如
string
自动写长度前缀)

BinaryReader读取时,
ReadString()
依赖UTF-8编码且要求前缀长度,不是原始字节读取

BinaryReader.ReadString()
不是读“直到

BinaryReader.ReadString()
不是读“直到\0”或“一行”,而是读一个7位编码的长度前缀(变长整数),再读对应字节数的UTF-8内容。如果文件不是用
BinaryWriter.WriteString()
写的,大概率抛
EndOfStreamException
或乱码。

”或“一行”,而是读一个7位编码的长度前缀(变长整数),再读对应字节数的UTF-8内容。如果文件不是用
BinaryWriter.WriteString()
写的,大概率抛
EndOfStreamException
或乱码。

确认写入端:只有
BinaryWriter.WriteString()
写的数据,才能用
BinaryReader.ReadString()
安全读
想读裸字节?改用
reader.ReadBytes(n)
reader.ReadChar()
等基础方法
编码不匹配?
BinaryReader
构造时可传
Encoding
,但
ReadString()
仍按自己的格式解析长度——编码只影响后续UTF-8解码

结构体序列化不能直接用BinaryWriter,需手动拆解字段

BinaryWriter
没有
Write(MyStruct)
重载。它不理解结构体布局、字段顺序、对齐或
[MarshalAs]
,直接
Marshal.Copy
又容易踩平台差异(比如
bool
占1字节还是4字节)。

安全做法:逐字段写,控制顺序和大小
writer.Write(point.X); // double
writer.Write(point.Y); // double
writer.Write(point.IsActive); // bool → 写为 byte 0/1 更可控
需要紧凑二进制?考虑
Span<byte></byte>
+
Unsafe.As<t byte></t>
(.NET Core 3+),但得确保
struct
blittable
且无引用类型
跨语言交互?别依赖
BinaryWriter
默认行为——它不保证与C/C++结构体二进制兼容

文件末尾判断别用
PeekChar()
BinaryReader
没有可靠的EOF探测方法

PeekChar()
在二进制流上意义不大(它尝试按当前编码读字符,可能失败或误判);
BaseStream.Position == BaseStream.Length
看似合理,但在网络流或压缩流中不可靠。

正确做法:明确知道要读多少项,或用长度头控制
// 写入时先写元素数量
writer.Write(items.Count);
foreach (var item in items) { ... }
// 读取时先读数量,再循环
int count = reader.ReadInt32();
for (int i = 0; i < count; i++) { ... }
真要试探读?捕获
EndOfStreamException
,但仅适用于“尽力而为”场景,不能作为主控逻辑
注意:
ReadByte()
返回
-1
表示EOF,但
ReadInt32()
等直接抛异常,行为不统一
实际用起来最常卡住的,是写入后没关流导致文件不完整,以及误把
ReadString()
当通用字符串读取器——它和写入端强绑定,换种方式写进去,就读不出来。

相关推荐