net core中byte数组如何高效转换为16进制字符串

news/2024/9/21 11:07:47/文章来源:https://www.cnblogs.com/hugogoos/p/18385298

在 .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 代码块方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/788828.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习爬虫day30-瑞数eval入口定位及VM

“VM”表示的是Virtual Machine(虚拟机),这些文件通常表示由浏览器生成和执行的虚拟机脚本环境中的临时脚本。这些脚本并不是项目源代码的一部分,也不是实际存在的物理文件。 它们在浏览器的内存中创建并执行;通过eval函数或者new Function方法,Chrome浏览器会创建一个&q…

【待做】【文件包含】PHP伪协议

https://mp.weixin.qq.com/s/sxjf5TppUcjIsfk836BMhA 【文件包含】PHP伪协议原创 菜鸟小新PHP支持的伪协议 file:// — 访问本地文件系统 http:// — 访问 HTTP(s) 网址 ftp:// — 访问 FTP(s) URLs php:// — 访问各个输入/输出流(I/O streams) zlib:// — 压缩流 data:// —…

centos基础设置

1.设置网络 # 配置网络 vi /etc/sysconfig/network-scripts/ifcfg-ens33 #将里面的onboard设置为yes2.修改计算机名 使用命令行: 打开终端。 使用 hostnamectl 命令可以直接修改主机名。例如,如果您想将主机名更改为 mynewhostname,您可以使用以下命令:sudo hostnamectl se…

【图论】【模板】2-SAT

2-SAT 定义 可以看一下洛谷模板题目的定义:思路 每个等式都可以理解为如果 \(x\) 不是条件规定的,那么 \(y\) 必须按照条件规定的,反过来也一样。 所以我们将一个数字拆成两个点,对于每个条件将代表取反 \(x\) 的点与 \(y\) 相连,将代表取反 \(y\) 的点与 \(x\) 相连。 比…

【字符串匹配】KMP

2024-8-28 最后更新时间 2024-8-28 \(\Large\mathcal{1,Recommendation}\) Knuth-Morris-Pratt 字符串查找算法,简称为KMP算法,常用于在一个文本串 S 内查找另一个文本 P 的出现位置,因为时间复杂度优异而被广泛使用。 这个算法由 Donald Knuth、Vaughan Pratt、James H. Mo…

两个月Crypto从入门到进阶专题第1天

绪论: 今天主要讲RSA的原理以及python的实现,RSA的历史这些就不讲了,RSA的历史你自己去搜视频看才有趣,三个大佬创造的RSA。1.RSA加密过程1.1选择p,q两个质数 (为什么选质数,后面就知道了,这里说一下学习方法:有一些步骤不知道为什么的,先看下去,可能后面会给你解答…

Android Qcom USB Driver学习(十一)

基于TI的Firmware Update固件升级的流程分析usb appliction layers的数据 USB Protocol Package①/② map to check password correct Package Format: Byte[0] = Report Id Byte[1] = Valid Length (0x21 = 33) Byte[2] = BSL Core Commands(0x11 RX Password) Byte[3] = Vali…

最简最速!C++版OpenCV安装配置教程Win/Mac!!!

Clion+OpenCV(C++版)开发环境配置教程Win/Mac平时在学习和比赛的时候都是使用的Python版本的OpenCV,最近遇到了一个项目使用的上位机性能有限于是决定视觉方面使用C++的OpenCV来节约上位机资源提高运行的速度,在查阅了网上的各种资料后发现这些资料参差不齐有些博客的方法绕来…

不可不知的WPF画笔(Brush)

在WPF中,屏幕上的所有内容,都是通过画笔(Brush)画上去的。如按钮的背景色,边框,文本框的前景和形状填充。借助画笔,可以绘制页面上的所有UI对象。不同画笔具有不同类型的输出( 如:某些画笔使用纯色绘制区域,其他画笔使用渐变、图案、图像或绘图)。在WPF中,屏幕上的…

缓存介绍

从业务层面上的堆数据库下性能瓶颈的解决方案: 分库分表、读写分离 程序员修神之路--略懂数据库集群读写分离而已缓存 缓存 (Cache):本质是数据交换的一段缓冲区,也可以称为一种存储数据的组件,主要用于减小数据交换双方速度不匹配的问题。 缓存在计算机世界里是一个常见并…

开源的工作流系统突出优点总结

随时欢迎大家一起了解开源的工作流系统的突出优势和特点。当前,想要实现高效率的办公,可以一起来了解低代码技术平台、开源的工作流系统的相关特点和功能优势。作为较受职场喜爱的平台产品,低代码技术平台拥有可视化才做界面、灵活、好维护操作等多个优势特点,在推动企业流…

2024年最新版Typora免费使用教程心得

在数字化时代,写作已成为我们日常沟通、知识分享的重要手段。然而,繁琐的排版格式常常让人望而却步。幸运的是,Markdown编辑器以其简洁的语法和高效的排版功能,为我们带来了福音。Typora是一款功能强大的文本编辑器,它采用所见即所得的编辑方式,能够让用户快速地编辑各种…