直接用 File.WriteAllBytes
最简单
如果内存里已有完整
byte[],且文件不大(比如几百 MB 以内),
File.WriteAllBytes是最直白的选择。它内部自动处理流打开、写入、关闭和异常清理,不用手动管理资源。
常见错误是误用
StreamWriter或
TextWriter写二进制数据——它们会做字符编码转换,导致内容损坏。
File.WriteAllBytes("data.bin", myByteArray) 即可完成写入
路径不存在时会抛出 DirectoryNotFoundException,需确保父目录已存在,或提前调用
Directory.CreateDirectory目标文件已存在时会被静默覆盖,无提示
大文件或流式场景必须用 FileStream
+ Write
当
byte[]极大(如 >500MB),或数据来自网络/设备等持续输入源时,一次性加载到内存不现实,必须边读边写。
关键点在于:不要用
FileStream.WriteAsync配合
await写小块数据,频繁 await 会显著拖慢吞吐;应尽量批量写入,并控制缓冲区大小。 用
new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 8192, useAsync: false)显式指定缓冲区,避免默认 4KB 在高 IO 场景下成为瓶颈 写入时优先调用
stream.Write(buffer, offset, count),而非
WriteAsync,除非上层明确需要异步非阻塞 务必用
using或
try/finally确保
stream.Dispose()被调用,否则文件句柄泄漏
注意 Encoding
相关函数不能用于二进制写入
看到
File.WriteAllText或
StreamWriter就容易条件反射去用——但这些全是为文本设计的,底层会把
byte[]当作某种编码(如 UTF-8)的字节序列再转义、补 BOM、处理换行符,结果和原始二进制完全对不上。
典型症状:写入一个 PNG 文件头
new byte[]{0x89, 0x50, 0x4E, 0x47} 后,用十六进制编辑器打开发现开头变成 0xEF, 0xBB, 0xBF, ...(UTF-8 BOM)或乱码字节。 只要目标是“原样保存字节”,就彻底避开
WriteAllText、
StreamWriter、
Encoding.GetBytes这类 API 例外:你确实想把二进制解释成字符串再存(比如 Base64 编码后存为文本),那另当别论
写入失败时常见错误信息和排查方向
权限、路径、磁盘空间问题在写二进制文件时更隐蔽,因为不涉及编码解析,错误往往直接暴露在 IO 层。
UnauthorizedAccessException:检查进程是否有目标目录写权限,特别是 Windows 上的受保护路径(如
C:\Program Files)或 macOS/Linux 的 root-only 目录
IOException带 “The process cannot access the file”:文件正被其他程序占用(如 Excel 打开了同名 .xlsx),或杀毒软件锁定了该路径
OutOfMemoryException在调用
WriteAllBytes时出现:说明数组本身过大,已超出 GC 可分配的连续内存块,必须切分或改用流式写入
实际写入逻辑越靠近底层 IO,越要盯住异常类型和消息里的具体路径、句柄状态——这些信息比“写入失败”四个字有用得多。
