如何识别字节数组编码并直接将其解码为字符串?
解决JSON字节数组解码乱码问题
问题根源
你的字节数组开头的255, 254是UTF-16 Little-Endian的字节顺序标记(BOM)。StreamReader会自动检测BOM并匹配对应编码,但直接使用new UnicodeEncoding()时,默认构造函数不会跳过BOM,会把这两个字节当成有效字符解析,导致开头乱码。
解决方案
1. 正确使用带BOM识别的Unicode编码
用UnicodeEncoding的重载构造函数,指定小端字节序并识别BOM:
var text3 = new UnicodeEncoding(false, true).GetString(data); Console.WriteLine(text3); // 输出正确的JSON字符串
- 第一个参数
false:指定使用Little-Endian(小端)格式,匹配你的字节数组 - 第二个参数
true:自动识别并跳过开头的BOM字节
2. 手动检测BOM识别编码
如果需要通用适配多种编码,可通过检测字节数组开头的BOM标记判断:
Encoding GetEncodingFromBom(byte[] data) { if (data.Length >= 2) { // UTF-16 Little-Endian BOM: FF FE if (data[0] == 0xFF && data[1] == 0xFE) return new UnicodeEncoding(false, true); // UTF-16 Big-Endian BOM: FE FF if (data[0] == 0xFE && data[1] == 0xFF) return new UnicodeEncoding(true, true); // UTF-8 BOM: EF BB BF if (data.Length >=3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) return new UTF8Encoding(true); // UTF-32 Little-Endian BOM: FF FE 00 00 if (data.Length >=4 && data[0] == 0xFF && data[1] == 0xFE && data[2] == 0x00 && data[3] == 0x00) return new UTF32Encoding(false, true); } // 默认 fallback,可根据业务调整 return Encoding.UTF8; } // 使用示例 var encoding = GetEncodingFromBom(data); var text4 = encoding.GetString(data); Console.WriteLine(text4);
3. 复用StreamReader的编码检测逻辑
不想手动写BOM检测的话,可以复用StreamReader的自动检测能力,无需读取整个流:
Encoding DetectEncoding(byte[] data) { using var ms = new MemoryStream(data); using var sr = new StreamReader(ms, detectEncodingFromByteOrderMarks: true); // 读取一个字符触发编码检测 sr.Read(); ms.Position = 0; // 重置流位置(后续需复用流时用) return sr.CurrentEncoding; } // 使用示例 var detectedEncoding = DetectEncoding(data); var text5 = detectedEncoding.GetString(data); Console.WriteLine(text5);
验证代码效果
替换正确的解码方式后,即可正常解析JSON:
var data = new byte[] { 255, 254, 123, 0, 34, 0, 114, 0, 101, 0, 99, 0, 116, 0, 115, 0, 34, 0, 58, 0, 91, 0, 93, 0, 44, 0, 34, 0, 116, 0, 101, 0, 120, 0, 116, 0, 34, 0, 58, 0, 34, 0, 34, 0, 125, 0 }; // 正确解码 var text = new UnicodeEncoding(false, true).GetString(data); dynamic json = JsonConvert.DeserializeObject<dynamic>(text); Console.WriteLine(json.text); // 输出空字符串 Console.WriteLine(json.rects); // 输出[]
内容的提问来源于stack exchange,提问作者Caleb Keller
相关产品推荐
相关产品推荐

