必须用与原始编码匹配的Encoding.GetString()解码字节数组,否则会导致乱码或异常;需明确字节来源并显式指定编码,避免依赖Encoding.Default,.NET Core/5+使用GBK等需先注册CodePagesEncodingProvider。

用 Encoding.GetString() 转字节数组,但编码必须匹配原始编码
字节数组转字符串不是无损“还原”,而是按指定编码规则去解释字节序列。如果用错编码(比如 UTF-8 编码的字节用 Encoding.ASCII.GetString() 解),就会出现乱码或异常。
- 常见错误现象:
符号大量出现、中文变成问号、ArgumentException提示“bytes are not a valid UTF-8 string” - 原始字节从哪来?如果是自己用
Encoding.UTF8.GetBytes()生成的,就只能用Encoding.UTF8.GetString()回转;如果是读取文件/网络流得到的,得查清对方声明或约定的编码(如 HTTPContent-Type: text/html; charset=gb2312) - 不要硬猜:Windows 简体中文系统默认 ANSI 是
GBK(.NET 中对应Encoding.GetEncoding("gb2312")或Encoding.GetEncoding(936)),但 .NET Core/.NET 5+ 默认不加载非 Unicode 编码,需手动注册CodePagesEncodingProvider.Instance
处理 GBK/GB2312 等中文编码时,先注册编码提供器
.NET Core 2.0+ 和 .NET 5+ 默认禁用多数非 Unicode 编码(如 gb2312、big5),直接调用 Encoding.GetEncoding("gb2312") 会抛出 ArgumentException:“No data is available for encoding 936”。
- 解决方法:在
Program.cs或应用启动处添加注册代码:Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- 之后才能安全使用:
Encoding.GetEncoding("gb2312")、Encoding.GetEncoding(936)、Encoding.GetEncoding("gbk") - 注意:该注册只需一次,且必须在任何
GetEncoding()调用前完成;ASP.NET Core 中建议放在Program.Main()开头
遇到无法识别的字节时,用 DecoderFallback 控制容错行为
当字节序列不符合目标编码规范(例如 UTF-8 中出现非法 continuation byte),默认会抛 DecoderFallbackException。生产环境通常需要降级处理,而非崩溃。
- 跳过非法字节:
var enc = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false);
- 替换成 :
var enc = Encoding.UTF8.Clone() as UTF8Encoding; enc?.DecoderFallback = DecoderFallback.ExceptionFallback;
(默认即如此) - 自定义替换字符(如
'?'):enc.DecoderFallback = new ReplacementDecoderFallback("?"); - 注意:
throwOnInvalidBytes: false只影响解码过程,不改变编码本身;对日志、解析等场景,宁可记录原始字节再排查,也不要静默丢弃
别依赖 Encoding.Default —— 它在不同平台含义完全不同
Encoding.Default 在 Windows 上通常是 GBK(代码页 936),但在 Linux/macOS 上是 UTF-8。跨平台项目中硬写 Encoding.Default.GetString(bytes),等于埋雷。
- 显式指定编码:除非你 100% 确认数据来源和运行环境,否则一律避免
Encoding.Default - 读文件时优先看 BOM:UTF-8 BOM(
EF BB BF)、UTF-16 BE(FE FF)、UTF-16 LE(FF FE)可辅助判断,但 BOM 并非强制存在 - 网络协议中优先以 header 为准:如 HTTP 的
charset、JSON RFC 明确要求 UTF-8,无需额外探测


















