BitConverter.ToString(bytes).Replace("-", "")可去除短横线;大写直接使用,小写需加ToLowerInvariant();大数组推荐string.Create+Span或.NET 5+的Convert.ToHexString。

BitConverter.ToString() 会多出短横线,怎么去掉
直接用 BitConverter.ToString(byte[]) 得到的是带短横线(-)的十六进制字符串,比如 "A1-B2-C3"。这不是大多数协议或日志需要的格式,得手动清理。
实操建议:
- 用
BitConverter.ToString(bytes).Replace("-", "")最快,适合小数组(几 KB 以内) - 对大数组(如 >100KB),用
string.Create()配合Span<char></char>手动填充,避免中间字符串分配 —— 性能高但代码略长 - 别用
bytes.Select(b => b.ToString("X2")).Aggregate((a,b) => a+b):LINQ + 字符串拼接在大数组下 GC 压力明显,且ToString("X2")每次都新建字符串
byte 转 hex 时大小写怎么控制
BitConverter.ToString() 固定输出大写;想小写就得自己转。但注意:不是所有场景都接受大小写混用,比如某些硬件协议只认小写,而 .NET 默认的 Base64 编码器、JSON 序列化器默认也倾向大写。
实操建议:
- 大写:直接用
BitConverter.ToString(bytes).Replace("-", "") - 小写:用
BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant()——ToLowerInvariant()比ToLower()更稳定,不受当前线程区域设置影响 - 别用
string.Concat(bytes.Select(b => b.ToString("x2"))):虽然能直接小写,但性能差,且"x2"在某些旧版 .NET(如 .NET Framework 4.6.1 之前)可能有格式化 bug
为什么 BitConverter.ToString() 的字节顺序是“从左到右”,但有时结果和预期相反
因为 BitConverter.ToString() 不做字节序转换,它只是把传入数组的每个 byte 按索引顺序转成两位十六进制。如果你拿的是一个 int 用 BitConverter.GetBytes(0x12345678) 得到的数组,在小端机上是 [0x78, 0x56, 0x34, 0x12],再转 hex 就是 "78563412" —— 看起来“反了”,其实是你忘了原始数值的内存布局。
实操建议:
- 确认你传给
BitConverter.ToString()的是“已经按目标顺序排好的字节数组”,而不是指望它帮你翻转 - 如果源数据是整数/浮点数且需网络字节序(大端),先调
IPAddress.HostToNetworkOrder()或手动翻转数组,再转 hex - 别假设
BitConverter会适配你的协议字节序 —— 它只忠实反映输入数组内容
不用 BitConverter,还有哪些安全又快的替代方案
.NET 5+ 提供了更底层、零分配的选项,尤其适合高频或内存敏感场景(如网络包解析、日志批量处理)。
实操建议:
- 用
Convert.ToHexString(byte[])(.NET 5+):原生支持大小写(Convert.ToHexString(bytes).ToLowerInvariant()),不加短横线,性能接近手写Span方案,且 API 简洁 - 旧版 .NET(如 4.7.2)只能靠
StringBuilder预分配容量 + 循环AppendFormat("{0:X2}", b),但要注意AppendFormat在高并发下有锁开销 - 别封装成通用扩展方法并默认返回
string:如果后续还要转成ReadOnlySpan<char></char>做进一步解析(比如找某个 hex 模式),直接生成char[]或用string.Create()更省事
真正容易被忽略的是:hex 字符串长度一定是原字节数组长度的两倍,但如果你中途做了截断、补零或编码转换(比如误当成 UTF-8 解码再 hex),结果就不可逆了。验证时最好拿几个固定字节(如 new byte[]{0, 1, 255})跑一遍,看输出是不是 "0001FF" —— 这比读文档快得多。










