C#中不使用Encoding与逐个Convert.ToByte()高效转换字符串为字节数组
嘿,这个需求我刚好研究过,给你分享两个高效的实现方案,完全满足你的要求——不用Encoding类,也不用对每个字符调用Convert.ToByte():
方案1:基于ASCII码偏移 + Span 的无额外分配实现
这是最直接且性能拉满的方案,因为我们知道字符'0'到'9'的ASCII码是连续的(从48到57),所以每个字符减去'0'的ASCII值就能直接得到对应的数字,再转为byte即可。用Span<T>还能避免额外的内存分配,同时减少CLR的边界检查开销。
public static byte[] StringToByteArray(string input) { if (input == null) throw new ArgumentNullException(nameof(input)); byte[] result = new byte[input.Length]; Span<byte> resultSpan = result.AsSpan(); ReadOnlySpan<char> inputSpan = input.AsSpan(); for (int i = 0; i < inputSpan.Length; i++) { // 输入确保是0-9字符,直接做ASCII偏移运算 resultSpan[i] = (byte)(inputSpan[i] - '0'); } return result; }
为什么高效?
- 没有装箱/拆箱操作,也没有调用任何Convert类方法,完全是底层的算术运算
- 使用Span
让内存访问更高效,编译器会自动优化掉多余的数组边界检查 - 仅分配一次结果数组,无额外内存开销
方案2:SIMD批量处理(适合超长字符串)
如果你的输入字符串特别长(比如几万甚至几十万字符),可以利用CPU的SIMD指令做批量处理,进一步提升速度。这个方案需要.NET Core 3.0+或.NET 5+支持,适合对性能极致追求的场景。
using System.Numerics; public static byte[] StringToByteArraySimd(string input) { if (input == null) throw new ArgumentNullException(nameof(input)); int length = input.Length; byte[] result = new byte[length]; ReadOnlySpan<char> inputSpan = input.AsSpan(); Span<byte> resultSpan = result.AsSpan(); int vectorSize = Vector<byte>.Count; int i = 0; // 批量处理每个Vector块,一次处理多个字符 for (; i <= length - vectorSize; i += vectorSize) { Vector<char> charVector = new Vector<char>(inputSpan.Slice(i, vectorSize)); Vector<byte> byteVector = Vector.Subtract(Vector.AsVectorByte(charVector), new Vector<byte>((byte)'0')); byteVector.CopyTo(resultSpan.Slice(i, vectorSize)); } // 处理剩余的不足一个Vector长度的字符 for (; i < length; i++) { resultSpan[i] = (byte)(inputSpan[i] - '0'); } return result; }
注意事项
- 只有当输入字符串足够长时,SIMD的优势才会体现出来,短字符串场景下反而可能因为Vector初始化开销变慢
- 不同CPU的Vector长度不同(比如x86是16字节,ARM是32字节),代码会自动适配
效果验证
比如输入字符串"0100",用上述任意一个方法都会得到结果:
byte[] result = { 0, 1, 0, 0 };
完全符合你的需求。
内容的提问来源于stack exchange,提问作者JP_99
相关产品推荐
相关产品推荐

