当前位置: 首页 > news >正文

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【maven】阿里云仓库配置
  • MySQL 中间件 MySQL-Router
  • 力扣229题详解:求众数 II 的多种解法与模拟面试问答
  • 由浅入深学习 C 语言:Hello World【基础篇】
  • 更改了ip地址怎么改回来
  • linux下一切皆文件,如何理解?
  • 搜索引擎通过分析网页标题中的关键词来判断内容的相关性
  • SAP BAPI-创建供应商客户主数据
  • Ai产品经理的探索:技能、机遇与未来展望
  • vivado U_SET
  • Zookeeper未授权访问的漏洞处理
  • Linux | 文件系统进阶:Inode与软硬链接艺术剖析
  • 怎么检测电脑的RAM?丨什么是RAM?
  • 【Linux系列】du命令详解
  • 数学基础 -- 线性函数与仿射函数
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • Create React App 使用
  • FineReport中如何实现自动滚屏效果
  • HTML5新特性总结
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Redis 中的布隆过滤器
  • SegmentFault 2015 Top Rank
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • v-if和v-for连用出现的问题
  • XML已死 ?
  • 高性能JavaScript阅读简记(三)
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 你不可错过的前端面试题(一)
  • 前端技术周刊 2019-01-14:客户端存储
  • 使用parted解决大于2T的磁盘分区
  • 写给高年级小学生看的《Bash 指南》
  • 用jquery写贪吃蛇
  • 字符串匹配基础上
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • 昨天1024程序员节,我故意写了个死循环~
  • ​​​​​​​STM32通过SPI硬件读写W25Q64
  • ​iOS实时查看App运行日志
  • #AngularJS#$sce.trustAsResourceUrl
  • (4)STL算法之比较
  • (二十四)Flask之flask-session组件
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (十)Flink Table API 和 SQL 基本概念
  • (十六)串口UART
  • (推荐)叮当——中文语音对话机器人
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .JPG图片,各种压缩率下的文件尺寸
  • .Net Web窗口页属性
  • .NET 漏洞分析 | 某ERP系统存在SQL注入