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

2024-08-29 08:20

本文主要是介绍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进制字符串的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117343

相关文章

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

python修改字符串值的三种方法

《python修改字符串值的三种方法》本文主要介绍了python修改字符串值的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录第一种方法:第二种方法:第三种方法:在python中,字符串对象是不可变类型,所以我们没办法直接

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

C#中字符串分割的多种方式

《C#中字符串分割的多种方式》在C#编程语言中,字符串处理是日常开发中不可或缺的一部分,字符串分割是处理文本数据时常用的操作,它允许我们将一个长字符串分解成多个子字符串,本文给大家介绍了C#中字符串分... 目录1. 使用 string.Split2. 使用正则表达式 (Regex.Split)3. 使用

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

Java将时间戳转换为Date对象的方法小结

《Java将时间戳转换为Date对象的方法小结》在Java编程中,处理日期和时间是一个常见需求,特别是在处理网络通信或者数据库操作时,本文主要为大家整理了Java中将时间戳转换为Date对象的方法... 目录1. 理解时间戳2. Date 类的构造函数3. 转换示例4. 处理可能的异常5. 考虑时区问题6.