C# StreamWriter写入额外字节:是Bug、预期行为还是遗漏说明?
为什么StreamWriter写入后MemoryStream长度多出3字节?
这个问题我之前也碰到过,其实不是Bug,是StreamWriter的一个默认行为——它会自动给UTF-8编码的流加上字节顺序标记(BOM),这就是导致MemoryStream长度多出3字节的原因。
问题原因拆解
你使用的Encoding.UTF8是一个默认包含BOM的编码实例,它的GetPreamble()方法会返回3个字节:0xEF, 0xBB, 0xBF。当StreamWriter第一次向流中写入数据时,会自动把这个BOM写入流的开头,这就额外增加了3字节的长度,所以最终memStream.Length是10240 + 3 = 10243。
你可以通过以下代码验证这一点:
memStream.Position = 0; var bomBytes = new byte[3]; memStream.Read(bomBytes, 0, 3); Console.WriteLine($"BOM字节:{string.Join(", ", bomBytes)}"); // 输出 239, 187, 191(对应EF BB BF)
解决方法
如果不需要UTF-8 BOM,你可以创建一个不生成BOM的UTF-8编码实例,把Encoding.UTF8替换成new UTF8Encoding(false)即可。修改后的代码如下:
var memStream = new MemoryStream(); using (var sw = new StreamWriter(memStream, new UTF8Encoding(false), 4194304 /* 4 MiB */, leaveOpen: true)) { var str = new string(Enumerable.Repeat(' ', 10240 /* 10 KiB */).ToArray()); Console.WriteLine(str.Length); Console.WriteLine(Encoding.UTF8.GetBytes(str).Length); sw.Write(str); sw.Flush(); Console.WriteLine(memStream.Length); }
运行这段代码后,MemoryStream的长度就会和预期一致,输出10240。
补充说明
关于这个行为,其实在StreamWriter的构造函数文档中有说明:当传入的编码实例的GetPreamble()方法返回非空字节数组时,StreamWriter会在第一次写入数据前,将这些前置字节写入流中。你之前查看的是Write(String)的方法文档,所以没找到相关说明,建议查看StreamWriter构造函数的文档细节。
内容的提问来源于stack exchange,提问作者amit9oct
相关产品推荐
相关产品推荐

