为何用StreamWriter与UTF8.GetBytes编码字符串为byte[]结果不同?
为什么StreamWriter和UTF8.GetBytes编码字符串得到的byte[]不一致?
这个问题的核心原因其实是**UTF-8字节顺序标记(BOM)**的差异,咱们一步步拆解:
1. 两种编码方式的行为差异
Encoding.UTF8.GetBytes(value)的行为:
这里使用的Encoding.UTF8实例默认是不输出UTF-8 BOM的。它只会将字符串直接转换为对应的UTF-8字节序列,不会添加任何额外的前缀字节。StreamWriter的默认行为:
当你调用new StreamWriter(memoryStream, Encoding.UTF8)时,StreamWriter会自动写入当前编码的前置码(Preamble)——也就是UTF-8的BOM(3字节:0xEF, 0xBB, 0xBF),然后再写入字符串的UTF-8字节序列。这就导致streamedData比data多了3个前缀字节,自然SequenceEqual会返回false。
2. 验证这个差异
你可以打印两个数组的长度来直观确认:
Console.WriteLine(data.Length); // 输出:10(对应"myTestValue"的UTF8字节数) Console.WriteLine(streamedData.Length); // 输出:13(3字节BOM + 10字节字符串)
3. 如何让两者结果一致?
有两种思路,根据你的需求选择:
方案一:让StreamWriter不输出BOM
显式创建一个不带BOM的UTF-8编码实例传给StreamWriter,这样它就不会写入前缀字节:
string value = "myTestValue"; byte[] data = Encoding.UTF8.GetBytes(value); byte[] streamedData; using (var memoryStream = new MemoryStream()) using (var streamWriter = new StreamWriter(memoryStream, new UTF8Encoding(false))) // 这里用UTF8Encoding(false)禁用BOM { streamWriter.Write(value); streamWriter.Flush(); streamedData = memoryStream.ToArray(); } // 现在data.SequenceEqual(streamedData)会返回true
方案二:让GetBytes也包含BOM
如果你需要保留BOM,可以将Encoding.UTF8.GetPreamble()和GetBytes的结果拼接:
byte[] bom = Encoding.UTF8.GetPreamble(); byte[] dataWithBom = new byte[bom.Length + data.Length]; bom.CopyTo(dataWithBom, 0); data.CopyTo(dataWithBom, bom.Length); // 此时dataWithBom.SequenceEqual(streamedData)会返回true
补充说明
为什么StreamWriter默认会写入BOM?这是因为早期部分系统或工具依赖BOM来识别文件的UTF-8编码类型,但现在大多数现代系统可以自动识别无BOM的UTF-8,所以如果不需要兼容老旧系统,推荐使用不带BOM的UTF-8编码。
内容的提问来源于stack exchange,提问作者user848765
相关产品推荐
相关产品推荐

