如何将字节数组转换为十六进制字符串,反之亦然?
当前回答
可以使用从.NET 5开始的Convert.ToHexString。还有一个用于反向操作的方法:Convert.FromHexString。
对于较旧版本的.NET,您可以使用:
public static string ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
or:
public static string ByteArrayToString(byte[] ba)
{
return BitConverter.ToString(ba).Replace("-","");
}
举个例子,这里有更多的方法。
反向转换如下:
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
使用Substring是与Convert.ToByte结合使用的最佳选项。有关详细信息,请参阅此答案。如果需要更好的性能,必须避免Convert.ToByte,然后才能删除SubString。
其他回答
这是我的尝试。我创建了一对扩展类来扩展字符串和字节。在大文件测试中,性能与Byte Manipulation 2相当。
下面的ToHexString代码是查找和移位算法的优化实现。它与Behrooz的方法几乎相同,但使用foreach进行迭代,计数器比显式索引更快。
在我的机器上,它排在Byte Manipulation 2之后,排在第二位,是非常可读的代码。以下测试结果也值得关注:
ToHexStringCharArrayWithCharArrayLookup:41589.69平均刻度(超过1000次),1.5倍ToHexStringCharArrayWithStringLookup:50764.06平均滴答(超过1000次),1.2XToHexStringStringBuilderWithCharArrayLookup:62812.87平均滴答(超过1000次),1.0X
根据上述结果,可以得出以下结论:
索引到字符串以执行查找与char数组在大型文件测试中非常重要。使用已知容量的StringBuilder与使用字符的惩罚创建字符串的已知大小的数组甚至更重要。
代码如下:
using System;
namespace ConversionExtensions
{
public static class ByteArrayExtensions
{
private readonly static char[] digits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string ToHexString(this byte[] bytes)
{
char[] hex = new char[bytes.Length * 2];
int index = 0;
foreach (byte b in bytes)
{
hex[index++] = digits[b >> 4];
hex[index++] = digits[b & 0x0F];
}
return new string(hex);
}
}
}
using System;
using System.IO;
namespace ConversionExtensions
{
public static class StringExtensions
{
public static byte[] ToBytes(this string hexString)
{
if (!string.IsNullOrEmpty(hexString) && hexString.Length % 2 != 0)
{
throw new FormatException("Hexadecimal string must not be empty and must contain an even number of digits to be valid.");
}
hexString = hexString.ToUpperInvariant();
byte[] data = new byte[hexString.Length / 2];
for (int index = 0; index < hexString.Length; index += 2)
{
int highDigitValue = hexString[index] <= '9' ? hexString[index] - '0' : hexString[index] - 'A' + 10;
int lowDigitValue = hexString[index + 1] <= '9' ? hexString[index + 1] - '0' : hexString[index + 1] - 'A' + 10;
if (highDigitValue < 0 || lowDigitValue < 0 || highDigitValue > 15 || lowDigitValue > 15)
{
throw new FormatException("An invalid digit was encountered. Valid hexadecimal digits are 0-9 and A-F.");
}
else
{
byte value = (byte)((highDigitValue << 4) | (lowDigitValue & 0x0F));
data[index / 2] = value;
}
}
return data;
}
}
}
下面是当我将代码放在我机器上的@patridge测试项目中时得到的测试结果。我还添加了一个从十六进制转换为字节数组的测试。使用我的代码的测试运行是ByteArrayToHexViaOptimizedLookupAndShift和HexToByteArrayViaByteManipulation。HexToByteArrayViaConvertToByte取自XXXX。HexToByteArrayViaSoapHexBinary是@Mykroft的答案。
Intel Pentium III Xeon处理器核心:4<br/>当前时钟速度:1576<br/>最大时钟速度:3092<br/>将字节数组转换为十六进制字符串表示ByteArrayToHexViaByteManipulation2:39366.64平均滴答(超过1000次),22.4倍ByteArrayToHexViaOptimizedLookupAndShift:41588.64平均刻度(超过1000次),21.2倍ByteArrayToHexViaLookup:55509.56次平均点击(超过1000次),15.9倍ByteArrayToHexViaByteManipulation:65349.12平均刻度(超过1000次),13.5XByteArrayToHexViaLookupAndShift:86926.87平均刻度(超过1000运行),10.2XByteArrayToHexStringViaBitConverter:平均139353.73滴答声(超过1000次),6.3XByteArrayToHexViaSoapHexBinary:314598.77平均刻度(超过1000次),2.8XByteArrayToHexStringViaStringBuilderForEachByteToString:344264.63平均刻度(超过1000次),2.6XByteArrayToHexStringViaStringBuilderAggregateByteToString:382623.44平均滴答声(超过1000次),2.3XByteArrayToHexStringViaStringBuilderForEachAppend格式:818111.95平均滴答声(超过1000次),1.1倍ByteArrayToHexStringViaStringConcatArray ConvertAll:839424.84平均值滴答声(超过1000次),1.1XByteArrayToHexStringViaStringBuilderAggregateAppend格式:867303.98平均刻度(超过1000次),1.0XByteArrayToHexStringViaStringJoinArray ConvertAll:平均882710.28滴答声(超过1000次),1.0X
如果您希望比BitConverter更灵活,但不希望使用那些笨重的90年代风格的显式循环,那么您可以这样做:
String.Join(String.Empty, Array.ConvertAll(bytes, x => x.ToString("X2")));
或者,如果您使用的是.NET 4.0:
String.Concat(Array.ConvertAll(bytes, x => x.ToString("X2")));
(后者来自对原帖子的评论。)
如果你想得到wcoenen报告的“4倍速度增长”,那么如果不明显:用hex[i]+hex[i+1]替换hex.Substring(i,2)
您还可以再进一步,通过在两个地方使用i++来消除i+=2。
您可以使用BitConverter.ToString方法:
byte[] bytes = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256}
Console.WriteLine( BitConverter.ToString(bytes));
输出:
00-01-02-04-08-10-20-40-80-FF
更多信息:BitConverter.ToString方法(Byte[])
有一个简单的一行解决方案尚未提及,它将十六进制字符串转换为字节数组(我们不在乎这里的否定解释,因为这无关紧要):
BigInteger.Parse(str, System.Globalization.NumberStyles.HexNumber).ToByteArray().Reverse().ToArray();
推荐文章
- 比较JUnit断言中的数组,简洁的内置方式?
- 数组到哈希Ruby
- 如何从枚举中选择一个随机值?
- 驻留在App_Code中的类不可访问
- 在链式LINQ扩展方法调用中等价于'let'关键字的代码
- dynamic (c# 4)和var之间的区别是什么?
- Visual Studio: ContextSwitchDeadlock
- 返回文件在ASP。Net Core Web API
- 自定义HttpClient请求头
- Java 8流和数组操作
- 如果我使用OWIN Startup.cs类并将所有配置移动到那里,我是否需要一个Global.asax.cs文件?
- VS2013外部构建错误"error MSB4019: The imported project <path> was not found"
- 在javascript中从平面数组构建树数组
- 从另一个列表id中排序一个列表
- 等待一个无效的异步方法