net core中byte数组如何高效转换为16进制字符串
在 .NET Core 中,如何把 byte[] 转换为 16 进制字符串?你能想到哪些方法?什么方式性能最好?今天和大家分享几种转换方式。
往往在处理字符串性能问题时,首先应该想到的是怎么想办法减少内存分配,怎么优化字符串构建。
下面就通过递进的方式介绍几种实现方式。
1. 使用 StringBuilder
在需要做大量字符串拼接的场景中,我们首先就会想到StringBuilder,相比string类型来说StringBuilder更高效。在这个例子中,它通过一次性分配足够的内存,然后配合字节格式化方法AppendFormat进行转换,并逐个追加每个字节的 16 进制表示,以此减少内存分配的开销。
using System;
using System.Text;
public class BytesToHexString
{
public static string ToHexStringStringBuilder(byte[] bytes)
{
StringBuilder hex = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
}
下面我们使用Benchmark对ToHexStringStringBuilder方法进行些基准测试,分别对字节数组长度为100、1000、10000个元素分别进行10000次测试,然后进行横向对比。

可以发现这个方法随着数组长度增加整体性能是在下降的。
2. 使用 BitConverter
BitConverter 是 .NET 中的内置类,它提供了一种简单的方式来转换基础数据类型为字符串。代码非常简洁,但是其本身只能输出固定格式如“0A-BC-99”,有连接符“-”并且字母都是大写,因此只适合简单需求,如果有复杂要求还行额外单独处理。
using System;
public class BytesToHexString
{
public static string ToHexStringBitConverter (byte[] bytes)
{
return BitConverter.ToString(bytes);
}
}
下面我们再次使用Benchmark对ToHexStringBitConverter方法进行些基准测试,分别对字节数组长度为100、1000、10000个元素各进行10000次测试,进行横向对比。

和StringBuilder方式对比,性能得到大幅度提升。
3. 使用 Convert(.NET5+)
Convert是 .NET 中的内置类,Convert.ToHexString是在 .NET 5 中引入的方法,用于将字节数组直接转换为十六进制字符串,改方法设计之初就考虑了性能,它在实现上减少了额外的内存分配和操作,因此它比 BitConverter.ToString 更高效。但是其本身只能输出固定格式如“0ABC99”,没有连接符“-”并且字母都是大写。
using System;
public class BytesToHexString
{
public static string ToHexStringConvert (byte[] bytes)
{
return Convert.ToHexString (bytes);
}
}
下面我们再次使用Benchmark对ToHexStringConvert方法进行些基准测试,分别对字节数组长度为100、1000、10000个元素各进行10000次测试,然后进行横向对比。

和BitConverter方式对比,性能也是大幅度提升。
4. 使用位运算
在将 byte[] 转换为 16 进制字符串时,每个字节会被转化为两个字符。因此,我们需要一个长度为 bytes.Length * 2 的字符数组来存储最终的 16 进制字符串。同时定义字符串hex = "0123456789abcdef";这个字符串中包含了所有可能的 16 进制字符,接下来遍历循环把每个字节通过位运算分解为2个 4 位的部分(高 4 位和低 4 位),然后通过字符串hex将高4位转为16进制第一个字符,低4位转为第二个字符。以下是一个示例实现:
using System;
public class BytesToHexString
{
public static string ToHexStringBitOperation (byte[] bytes)
{
char[] hexChars = new char[bytes.Length * 2];
const string hex = "0123456789abcdef";
for (int i = 0; i < bytes.Length; i++)
{
hexChars[i * 2] = hex[bytes[i] >> 4];
hexChars[i * 2 + 1] = hex[bytes[i] & 0x0F];
}
return new string(hexChars);
}
}
下面我们再次使用Benchmark对ToHexStringBitOperation方法进行些基准测试,分别对字节数组长度为100、1000、10000个元素各进行10000次测试,然后进行横向对比。

虽然和BitConverter相比,性能提升3倍多,但是和Convert方式相比却有所差距。
如果对位运算不是很明白的,可以留言,后面可以单独出一篇文章讲解一下。
5. 使用 unsafe 代码块(高级)
如果你需要极致的性能,并且可以接受 unsafe 代码,你可以使用指针来操作字节数组。这种方法可以极大地提高性能,但需要注意内存安全问题。
using System;
public class BytesToHexString
{
public static unsafe string ToHexStringUnsafe(byte[] bytes)
{
const string hex = "0123456789ABCDEF";
var hexChars = new char[bytes.Length * 2];
fixed (byte* bytePtr = bytes)
{
fixed (char* charPtr = hexChars)
{
byte* source = bytePtr;
char* dest = charPtr;
for (int i = 0; i < bytes.Length; i++)
{
byte b = source[i];
dest[i * 2] = hex[b >> 4];
dest[i * 2 + 1] = hex[b & 0x0F];
}
}
}
return new string(hexChars);
}
}
下面我们再次使用Benchmark对ToHexStringBitConverter方法进行些基准测试,分别对字节数组长度为100、1000、10000个元素各进行10000次测试,然后进行横向对比。

和位运算方式相比,并没有像前面的大幅提升,相差无几。
下面看看5种方法,整体对比情况:

通过上面一系列测试,我们可以得到如下总结:
灵活性:StringBuilder、位操作、unsafe 代码块 > BitConverter、Convert
性能:Convert > unsafe 代码块 > 位操作 > BitConverter > StringBuilder
如果只是要把字节数组转化为字符串没有什么要求,那么直接选择官方自带方法Convert.ToHexString;如果对于输出格式有要求,则可以用位操作的方式自己实现个性化需求;当在极端特殊情况下可以考虑unsafe 代码块方式。
net core中byte数组如何高效转换为16进制字符串的更多相关文章
- java中把字节数组转换为16进制字符串
把字符串数组转换为16进制字符串 import java.security.MessageDigest; public class StringUtil { public StringUtil() { ...
- js中如何把RGB颜色转换为16进制颜色
将RGB颜色值转换为16进制颜色值,主要是将 R.G.B 值分别转换为对应的十六进制值,填入 #RRGGBB 中. 推荐在线颜色转换工具:http://www.ecjson.com/rgbhex/ 例 ...
- java中如何将byte[]里面的数据转换成16进制字符串
原文链接: http://zhidao.baidu.com/link?url=RmLDjr4PtP_oUE5J2pKNZSvlHt1K7HcCh4-03Y7VkXYhJ0kawg01CtKHZc2uB ...
- hex(x) 将整数x转换为16进制字符串
>>> a = 122 >>> b = 344 >>> c = hex(a) >>> d = hex(b) >>&g ...
- java中 16进制字符串 与普通字符串 与 byte数组 之间的转化
方法依赖commons-codec包 maven的引入方式如下 <dependency> <groupId>commons-codec</groupId> < ...
- Java中byte与16进制字符串的互相转换
* Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串. * @param s ...
- [转]Java中byte与16进制字符串的互相转换
Java中byte用二进制表示占用8位,而我们知道16进制的每个字符需要用4位二进制位来表示(23 + 22 + 21 + 20 = 15),所以我们就可以把每个byte转换成两个相应的16进制字符, ...
- BYTE数组与16进制字符串互转
//字节数组转换为HEX 字符串const string Byte2HexString(const unsigned char* input, const int datasize) { ]; ; j ...
- java中byte[] 和16进制字符串互转
//将byte[]转换为16进制字符串 public static String byte2hex(byte[] b) { StringBuilder hs = new StringBuilder() ...
- 字节数组(byte[])与16进制字符串转换
/// <summary> /// 转换扩展类 /// </summary> public static class ConvertExtend { /// <summa ...
随机推荐
- 移动WEB开发之 -- flex布局
flex布局原理 常见的父项属性 flex-direction设置主轴方向 justify-content 设置主轴上的子元素排列方式 flex-wrap属性 align-items属性 align- ...
- JavaScript系列:JS实现复制粘贴文字以及图片
目录 一. 基于 Clipboard API 复制文字(推荐) 基本概念 主要方法 使用限制 实际应用示例 二.基于 document.execCommand('copy') 缺陷 实际应用示例 说明 ...
- <script> 和 <script setup> 的一些主要差别
<script setup> 是 Vue 3 中的新特性,它是一种简化和更具声明性的语法,用于编写组件的逻辑部分.相比之下,<script> 是 Vue 2 中常用的编写组件逻 ...
- [oeasy]python0085_ASCII之父_Bemer_COBOL_数据交换网络
编码进化 回忆上次内容 上次 回顾了 字符编码的 进化过程 IBM 在数字化过程中 作用 非常大 IBM 的 BCDIC 有 黑历史 6-bit的 BCDIC 直接进化成 8-bit的 EBCDIC ...
- [oeasy]python0078_设置索引颜色_index_color_ansi_控制终端颜色
更多颜色 回忆上次内容 上次 了解了 高亮颜色 91-97 是 高亮 前景色 101-107是 高亮 背景色 颜色种类 在原来基础上 增加了一些 但也非常有限 还想要 更精细的颜色 有可能吗?? 更多 ...
- 题解:CF1985E Secret Box
设长宽高分别为 \(a,b,c\). 由题意可轻松的得到以下求方案数公式. \((x-a+1)(y-b+1)(z-c+1)\) 然后根据这个公式模拟即可. AC Code
- LeetCode102.二叉树的层序遍历
LeetCode题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/submissions/548489149/ 题 ...
- 什么是spring.factories,引入未知模块报错如何解决
对于maven中引入其他外部包加入容器的过程,需要用到spring.factories spring.factories的作用:将自动配置类与对应的配置类集中在一起,方便springboot自动装配, ...
- Jmeter函数助手12-threadNum
threadNum函数用于获取当前线程编号.该函数没有参数,直接引用即可. 1.线程数可在组件[测试计划->线程组]设置.如下是不传入循环次数的${__threadNum}. "调试取 ...
- 03 OLED显示屏实现
目录 前言 一.软件模拟IIC协议 1.开启IIC协议 2.结束IIC协议 3.传输数据 二.OLED的操作 1.传输数据的准备 2.写入命令 3.写入数据 4.初始化函数 5.设置光标 6.显示字符 ...