C#中byte[]与string转换必须显式指定编码,推荐UTF-8;Encoding.Default不可靠,GB2312等旧编码需额外配置;Base64和BitConverter非编码转换;接收数据时须用实际长度解码。
![c# byte[] 和 string 如何转换](https://img.php.cn/upload/article/001/221/864/176757811045228.png)
byte[] 和 string 的转换在 C# 中不是“无损直连”,而是依赖编码(Encoding)的有损映射过程。直接用 Encoding.Default 或乱配编码,轻则中文变问号,重则解码失败抛 ArgumentException 或静默截断。
用 Encoding.UTF8 是最安全的默认选择
绝大多数现代场景(网络通信、JSON、文件存储、API 交互)都默认使用 UTF-8。它兼容 ASCII,能正确表示中文、emoji、特殊符号,且 .NET 默认字符串内部是 UTF-16,但跨边界传输时 UTF-8 是事实标准。
string text = "你好,Hello ?"; byte[] bytes = Encoding.UTF8.GetBytes(text); string roundTrip = Encoding.UTF8.GetString(bytes); // ✅ 正确还原
- ✅ 推荐始终显式写
Encoding.UTF8,别用Encoding.Default(它随系统区域设置变化,Windows 上可能是 GB2312/GBK,Linux/macOS 上通常是 UTF-8,极难统一) - ⚠️
Encoding.Unicode实际对应 UTF-16 LE(带 BOM),生成的byte[]长度是 UTF-8 的约 2 倍,且在网络传输中容易被中间件误判或截断 - ❌
Encoding.ASCII只支持 0–127,遇到中文会变成?或直接丢字节
接收字节数组时必须知道原始编码,否则无法还原
常见错误:从 socket、串口、文件读到一坨 byte[],直接 Encoding.UTF8.GetString(buffer),结果中文全乱码。
- 真实场景中,编码信息通常来自协议约定(如 HTTP
Content-Type: text/plain; charset=utf-8)、文档说明,或对方明确告知 - 如果你控制发送端,就固定用 UTF-8 并文档化;如果对接第三方,先查清其输出编码(比如旧系统可能用
GB2312)
// 对方明确说“数据是 GB2312 编码”
byte[] gb2312Bytes = File.ReadAllBytes("legacy.txt");
string legacyText = Encoding.GetEncoding("GB2312").GetString(gb2312Bytes);
-
Encoding.GetEncoding("GB2312")在 .NET Core/.NET 5+ 需要额外安装System.Text.Encoding.CodePagesNuGet 包并调用Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) - 不推荐在新项目中主动用 GB2312 / BIG5 等旧编码,除非维护遗留系统
不要用 BitConverter.ToString() 或 Convert.ToBase64String() 替代编码转换
它们用途完全不同:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
-
BitConverter.ToString(bytes)→ 把每个字节转成两位十六进制 + 连字符(如"48-65-6C-6C-6F"),本质是调试/日志用的可读表示,不是文本内容本身 -
Convert.ToBase64String(bytes)→ 是二进制安全编码,用于把任意byte[](含 \0、控制字符等)转成纯 ASCII 字符串,常用于 JWT、HTTP Authorization、URL 参数等 - 它们和“字符串内容 ↔ 字节语义”无关:你不能把
"你好"先转 Base64 再当普通字符串显示,那只是乱码(如"6L+Z5piv")
string original = "abc"; byte[] utf8Bytes = Encoding.UTF8.GetBytes(original); string base64 = Convert.ToBase64String(utf8Bytes); // "YWJj" string decoded = Encoding.UTF8.GetString(Convert.FromBase64String(base64)); // ✅ 还原为 "abc" // 但 base64 本身不是“字符串”,它只是字节的编码载体
- ✅ Base64 适合:需要把二进制塞进文本字段(XML、JSON、URL)的场景
- ❌ Base64 不适合:代替
Encoding做自然语言文本转换
接收网络/IO 数据时记得处理实际长度,别直接用整个 buffer
典型坑:用 socket.Receive(buffer) 读取,返回值是真实接收字节数 int actualLength,但很多人直接传 buffer.Length 给 GetString,导致末尾一堆 \0 或乱码。
byte[] buffer = new byte[1024]; int received = client_socket.Receive(buffer); string message = Encoding.UTF8.GetString(buffer, 0, received); // ✅ 关键:用 received,不是 buffer.Length
-
Encoding.UTF8.GetString(buffer)会尝试解码整个数组,包括未填充部分(可能全是 0),而 UTF-8 解码器对 \0 敏感,可能提前终止或报错 - 同理,
Encoding.UTF8.GetString(bytes, offset, count)的count必须准确 —— 它不是“最大长度”,而是“有效字节数”
真正麻烦的地方不在怎么写,而在于:编码从来不是孤立操作,它是协议的一部分。发的人没说清楚用什么编码,收的人再怎么选对 Encoding 类也白搭。









