字节[]到十六进制字符串

如何将byte[]转换为string?每次我尝试,我都

系统。Byte []

而不是数值。

另外,我如何得到十六进制而不是小数的值?

628496 次浏览

你必须知道以字节表示的字符串的编码,但你可以说System.Text.UTF8Encoding.GetString(bytes)System.Text.ASCIIEncoding.GetString(bytes)。(我是根据记忆做的,所以API可能不完全正确,但它非常接近。)

第二个问题的答案,见这个问题

我不经常把字节转换成十六进制所以我不知道有没有更好的方法,但这里有一种方法。

StringBuilder sb = new StringBuilder();
foreach (byte b in myByteArray)
sb.Append(b.ToString("X2"));


string hexString = sb.ToString();

正如其他人所说,这取决于字节数组中值的编码方式。尽管如此,您还是需要非常小心地处理这类事情,否则您可能会尝试转换未被所选编码处理的字节。

Jon Skeet有一个关于。net中的编码和unicode的篇好文章。推荐阅读。

十六进制,Linq-fu:

string.Concat(ba.Select(b => b.ToString("X2")).ToArray())

与时俱进

正如@RubenBartelink所指出的,没有将IEnumerable<string>转换为数组:ba.Select(b => b.ToString("X2"))的代码在4.0之前不能工作,相同的代码现在在4.0上可以工作。

这段代码…

byte[] ba = { 1, 2, 4, 8, 16, 32 };


string s = string.Concat(ba.Select(b => b.ToString("X2")));
string t = string.Concat(ba.Select(b => b.ToString("X2")).ToArray());


Console.WriteLine (s);
Console.WriteLine (t);

...在。net 4.0之前,输出是:

System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[System.Byte,System.String]
010204081020

在。net 4.0以后,字符串。Concat有一个接受IEnumerable的重载。因此,在4.0版本中,上述代码对于变量s和t将有相同的输出

010204081020
010204081020

在4.0之前,ba.Select(b => b.ToString("X2"))会重载(object arg0),要使IEnumerable<string>进行适当的重载,即(params string[] values),我们需要将IEnumerable<string>转换为字符串数组。4.0之前,字符串。Concat有10个过载功能,在4.0现在是12个

有一个内置的方法:

byte[] data = { 1, 2, 4, 8, 16, 32 };


string hex = BitConverter.ToString(data);

结果:01-02-04-08-10-20

如果你想要没有破折号,只需删除它们:

string hex = BitConverter.ToString(data).Replace("-", string.Empty);

结果:010204081020

如果你想要一个更紧凑的表示,你可以使用Base64:

string base64 = Convert.ToBase64String(data);

结果:AQIECBAg

你把LINQ和字符串方法结合起来:

string hex = string.Join("",
bin.Select(
bin => bin.ToString("X2")
).ToArray());

我喜欢将扩展方法用于这样的转换,即使它们只是包装标准库方法。在十六进制转换的情况下,我使用以下手工调优(即)算法:

public static string ToHex(this byte[] bytes)
{
char[] c = new char[bytes.Length * 2];


byte b;


for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);


b = ((byte)(bytes[bx] & 0x0F));
c[++cx]=(char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
}


return new string(c);
}


public static byte[] HexToBytes(this string str)
{
if (str.Length == 0 || str.Length % 2 != 0)
return new byte[0];


byte[] buffer = new byte[str.Length / 2];
char c;
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
{
// Convert first half of byte
c = str[sx];
buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);


// Convert second half of byte
c = str[++sx];
buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
}


return buffer;
}

用LINQ做这件事的好方法…

var data = new byte[] { 1, 2, 4, 8, 16, 32 };
var hexString = data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();

下面是另一种方法:

public static string ByteArrayToHexString(byte[] Bytes)
{
StringBuilder Result = new StringBuilder(Bytes.Length * 2);
string HexAlphabet = "0123456789ABCDEF";


foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}


return Result.ToString();
}


public static byte[] HexStringToByteArray(string Hex)
{
byte[] Bytes = new byte[Hex.Length / 2];
int[] HexValue = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };


for (int x = 0, i = 0; i < Hex.Length; i += 2, x += 1)
{
Bytes[x] = (byte)(HexValue[Char.ToUpper(Hex[i + 0]) - '0'] << 4 |
HexValue[Char.ToUpper(Hex[i + 1]) - '0']);
}


return Bytes;
}

或者,你可以像这样预先构建翻译表,以获得更快的结果:

http://blogs.msdn.com/b/blambert/archive/2009/02/22/blambert-codesnip-fast-byte-array-to-hex-string-conversion.aspx

下面是一个字节数组(byte[])的扩展方法,例如:

var b = new byte[] { 15, 22, 255, 84, 45, 65, 7, 28, 59, 10 };
Console.WriteLine(b.ToHexString());




public static class HexByteArrayExtensionMethods
{
private const int AllocateThreshold = 256;
private const string UpperHexChars = "0123456789ABCDEF";
private const string LowerhexChars = "0123456789abcdef";
private static string[] upperHexBytes;
private static string[] lowerHexBytes;


public static string ToHexString(this byte[] value)
{
return ToHexString(value, false);
}


public static string ToHexString(this byte[] value, bool upperCase)
{
if (value == null)
{
throw new ArgumentNullException("value");
}


if (value.Length == 0)
{
return string.Empty;
}


if (upperCase)
{
if (upperHexBytes != null)
{
return ToHexStringFast(value, upperHexBytes);
}


if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, UpperHexBytes);
}


return ToHexStringSlow(value, UpperHexChars);
}


if (lowerHexBytes != null)
{
return ToHexStringFast(value, lowerHexBytes);
}


if (value.Length > AllocateThreshold)
{
return ToHexStringFast(value, LowerHexBytes);
}


return ToHexStringSlow(value, LowerhexChars);
}


private static string ToHexStringSlow(byte[] value, string hexChars)
{
var hex = new char[value.Length * 2];
int j = 0;


for (var i = 0; i < value.Length; i++)
{
var b = value[i];
hex[j++] = hexChars[b >> 4];
hex[j++] = hexChars[b & 15];
}


return new string(hex);
}


private static string ToHexStringFast(byte[] value, string[] hexBytes)
{
var hex = new char[value.Length * 2];
int j = 0;


for (var i = 0; i < value.Length; i++)
{
var s = hexBytes[value[i]];
hex[j++] = s[0];
hex[j++] = s[1];
}


return new string(hex);
}


private static string[] UpperHexBytes
{
get
{
return (upperHexBytes ?? (upperHexBytes = new[] {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" }));
}
}


private static string[] LowerHexBytes
{
get
{
return (lowerHexBytes ?? (lowerHexBytes = new[] {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" }));
}
}
}

.Net5.0更新

感谢@antoninkriz的基准比较,我们可以看到Convert.ToHexString到目前为止今天的明显赢家

使用Convert.ToHexString以外的任何方法都是愚蠢的。在我看来,它在可读性、性能和安全性方面明显更胜一筹


剩下的是2012年4月10日之前的数据:

我想我应该尝试比较这里列出的每个方法的速度。我基于这个编写了速度测试代码。

结果是BitConverter+String。替换似乎比大多数其他简单的方法更快。但是速度可以通过像Nathan Moinvaziri的ByteArrayToHexString或Kurt's ToHex这样的算法来提高。

我还发现了一个有趣的字符串。连接和串。对于长字符串,Join比StringBuilder实现慢得多,但对于较短的数组也类似。可能是由于在较长的字符串上扩展StringBuilder,所以设置初始大小应该消除这种差异。

  • 从这里的答案中抽取每一位代码:
  • BitConvertRep =答案由Guffa, BitConverter和字符串。取代(我建议在大多数情况下,[编辑:]你不能使用Convert.ToHexString)
  • StringBuilder =答案由Quintin Robinson, foreach char StringBuilder。附加
  • LinqConcat = Michael Buen的回答,字符串。Concat的Linq建立数组
  • LinqJoin =答案由mloskot,字符串。连接Linq构建的数组
  • LinqAgg =回答马修怀特,IEnumerable。使用StringBuilder聚合
  • ToHex = Answer by Kurt,设置数组中的字符,使用字节值来获得十六进制
  • ByteArrayToHexString =由Nathan Moinvaziri回答,与上面的ToHex大致相同的速度,并且可能更容易阅读(我建议为了速度,[编辑:]你不能使用Convert.ToHexString)
  • ToHexFromTable =由Nathan Moinvaziri链接的答案,对我来说,这几乎与上面2个相同的速度,但需要256个字符串的数组始终存在

: LONG_STRING_LENGTH = 1000 * 1024;

  • BitConvertRep计算时间消耗27202毫秒(最快内置/简单)
  • StringBuilder计算时间消耗75,723 ms (StringBuilder没有重新分配)
  • LinqConcat计算时间流逝182,094毫秒
  • LinqJoin计算时间流逝181,142毫秒
  • LinqAgg计算时间消耗93,087 ms (StringBuilder与重新分配)
  • ToHex计算时间流逝19167毫秒(最快)

使用:LONG_STRING_LENGTH = 100 * 1024;,结果相似

  • BitConvertReplace计算时间流逝3431毫秒
  • StringBuilder计算时间流逝8289毫秒
  • LinqConcat计算时间流逝21512毫秒
  • LinqJoin计算时间流逝19433毫秒
  • LinqAgg计算时间流逝9230毫秒
  • 时间流逝1976毫秒

With: int MANY_STRING_COUNT = 1000; int MANY_STRING_LENGTH = 1024; (与第一次测试相同的字节计数,但在不同的数组中)

  • BitConvertReplace计算时间25,680 ms
  • StringBuilder计算时间耗时78,411毫秒
  • LinqConcat计算时间经过101,233毫秒
  • LinqJoin计算Time Elapsed 99,311 ms
  • LinqAgg计算时间消耗84,660毫秒
  • ToHex计算时间耗时18221毫秒

使用:int MANY_STRING_COUNT = 2000; int MANY_STRING_LENGTH = 20;

  • BitConvertReplace计算时间消耗1347毫秒
  • StringBuilder计算时间消耗3234毫秒
  • LinqConcat计算时间消耗5013毫秒
  • LinqJoin计算时间流逝4826毫秒
  • LinqAgg计算时间流逝3589毫秒
  • ToHex计算时间耗时772毫秒

我使用的测试代码:

void Main()
{
int LONG_STRING_LENGTH = 100 * 1024;
int MANY_STRING_COUNT = 1024;
int MANY_STRING_LENGTH = 100;


var source = GetRandomBytes(LONG_STRING_LENGTH);


List<byte[]> manyString = new List<byte[]>(MANY_STRING_COUNT);
for (int i = 0; i < MANY_STRING_COUNT; ++i)
{
manyString.Add(GetRandomBytes(MANY_STRING_LENGTH));
}


var algorithms = new Dictionary<string,Func<byte[], string>>();
algorithms["BitConvertReplace"] = BitConv;
algorithms["StringBuilder"] = StringBuilderTest;
algorithms["LinqConcat"] = LinqConcat;
algorithms["LinqJoin"] = LinqJoin;
algorithms["LinqAgg"] = LinqAgg;
algorithms["ToHex"] = ToHex;
algorithms["ByteArrayToHexString"] = ByteArrayToHexString;


Console.WriteLine(" === Long string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
pair.Value(source);
});
}


Console.WriteLine(" === Many string test");
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
foreach (var str in manyString)
{
pair.Value(str);
}
});
}
}


// Define other methods and classes here
static void TimeAction(string description, int iterations, Action func) {
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}


//static byte[] GetRandomBytes(int count) {
//  var bytes = new byte[count];
//  (new Random()).NextBytes(bytes);
//  return bytes;
//}
static Random rand = new Random();
static byte[] GetRandomBytes(int count) {
var bytes = new byte[count];
rand.NextBytes(bytes);
return bytes;
}




static string BitConv(byte[] data)
{
return BitConverter.ToString(data).Replace("-", string.Empty);
}
static string StringBuilderTest(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length*2);
foreach (byte b in data)
sb.Append(b.ToString("X2"));


return sb.ToString();
}
static string LinqConcat(byte[] data)
{
return string.Concat(data.Select(b => b.ToString("X2")).ToArray());
}
static string LinqJoin(byte[] data)
{
return string.Join("",
data.Select(
bin => bin.ToString("X2")
).ToArray());
}
static string LinqAgg(byte[] data)
{
return data.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v.ToString("X2"))
).ToString();
}
static string ToHex(byte[] bytes)
{
char[] c = new char[bytes.Length * 2];


byte b;


for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');


b = ((byte)(bytes[bx] & 0x0F));
c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0');
}


return new string(c);
}
public static string ByteArrayToHexString(byte[] Bytes)
{
StringBuilder Result = new StringBuilder(Bytes.Length*2);
string HexAlphabet = "0123456789ABCDEF";


foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}


return Result.ToString();
}

还有一个类似的答案,我还没有比较我们的结果。

:

byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x0D, 0x0E, 0x0F };
string hex = string.Empty;
data.ToList().ForEach(b => hex += b.ToString("x2"));
// use "X2" for uppercase hex letters
Console.WriteLine(hex);

结果:0102030d0e0f

private static string GuidToRaw(Guid guid)
{
byte[] bytes = guid.ToByteArray();


int сharCount = bytes.Length * 2;
char[] chars = new char[сharCount];


int index = 0;
for (int i = 0; i < сharCount; i += 2)
{
byte b = bytes[index++];
chars[i] = GetHexValue((int)(b / 16));
chars[i + 1] = GetHexValue((int)(b % 16));
}
return new string(chars, 0, chars.Length);
}


private static char GetHexValue(int i)
{
return (char)(i < 10 ? i + 48 : i + 55);
}

我想我做了一个更快的字节数组到字符串转换器:

public static class HexTable
{
private static readonly string[] table = BitConverter.ToString(Enumerable.Range(0, 256).Select(x => (byte)x).ToArray()).Split('-');


public static string ToHexTable(byte[] value)
{
StringBuilder sb = new StringBuilder(2 * value.Length);


for (int i = 0; i < value.Length; i++)
sb.Append(table[value[i]]);


return sb.ToString();
}

并且测试设置:

static void Main(string[] args)
{
const int TEST_COUNT = 10000;
const int BUFFER_LENGTH = 100000;


Random random = new Random();


Stopwatch sw = new Stopwatch();
Stopwatch sw2 = new Stopwatch();


byte[] buffer = new byte[BUFFER_LENGTH];
random.NextBytes(buffer);


sw.Start();
for (int j = 0; j < TEST_COUNT; j++)
HexTable.ToHexTable(buffer);


sw.Stop();


sw2.Start();
for (int j = 0; j < TEST_COUNT; j++)
ToHexChar.ToHex(buffer);


sw2.Stop();


Console.WriteLine("Hex Table Elapsed Milliseconds: {0}", sw.ElapsedMilliseconds);
Console.WriteLine("ToHex Elapsed Milliseconds: {0}", sw2.ElapsedMilliseconds);
}

ToHexChar.ToHEx()方法是前面所示的ToHex()方法。

结果如下:

HexTable = 11808 ms ToHEx = 12168ms

它看起来可能没有太大的不同,但它仍然更快:)

再向堆中添加一个答案,我使用了一个System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary类,它可以将字节转换为十六进制:

string hex = new SoapHexBinary(bytes).ToString();
byte[] bytes = SoapHexBinary.Parse(hex).Value;

不确定它与其他实现(基准)相比如何,但在我看来,它非常简单——特别是从十六进制转换回字节。

这里没人提到你为什么会有"系统"字节[]"字符串,而不是值,所以我将。

当对象隐式转换为String类型时,程序将默认使用对象的public String ToString()方法,该方法继承自System.Object:

public virtual string ToString()
{
return this.GetType().ToString();
}

如果你发现你经常进行这种转换,你可以简单地创建一个包装器类,并像这样重写这个方法:

public override string ToString()
{
// do the processing here
// return the nicely formatted string
}

现在,每次打印这个包装器对象时,你将得到你自己的值,而不是this.GetType().ToString()的值。

我想我应该给出一个答案。从我的测试来看,这种方法是最快的

public static class Helper
{
public static string[] HexTbl = Enumerable.Range(0, 256).Select(v => v.ToString("X2")).ToArray();
public static string ToHex(this IEnumerable<byte> array)
{
StringBuilder s = new StringBuilder();
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
public static string ToHex(this byte[] array)
{
StringBuilder s = new StringBuilder(array.Length*2);
foreach (var v in array)
s.Append(HexTbl[v]);
return s.ToString();
}
}

我不确定你是否需要这样做的性能,但这里是最快的方法转换字节[]到十六进制字符串,我能想到:

static readonly char[] hexchar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string HexStr(byte[] data, int offset, int len, bool space = false)
{
int i = 0, k = 2;
if (space) k++;
var c = new char[len * k];
while (i < len)
{
byte d = data[offset + i];
c[i * k] = hexchar[d / 0x10];
c[i * k + 1] = hexchar[d % 0x10];
if (space && i < len - 1) c[i * k + 2] = ' ';
i++;
}
return new string(c, 0, c.Length);
}

非常快速的扩展方法(带反转):

public static class ExtensionMethods {
public static string ToHex(this byte[] data) {
return ToHex(data, "");
}
public static string ToHex(this byte[] data, string prefix) {
char[] lookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
int i = 0, p = prefix.Length, l = data.Length;
char[] c = new char[l * 2 + p];
byte d;
for(; i < p; ++i) c[i] = prefix[i];
i = -1;
--l;
--p;
while(i < l) {
d = data[++i];
c[++p] = lookup[d >> 4];
c[++p] = lookup[d & 0xF];
}
return new string(c, 0, c.Length);
}
public static byte[] FromHex(this string str) {
return FromHex(str, 0, 0, 0);
}
public static byte[] FromHex(this string str, int offset, int step) {
return FromHex(str, offset, step, 0);
}
public static byte[] FromHex(this string str, int offset, int step, int tail) {
byte[] b = new byte[(str.Length - offset - tail + step) / (2 + step)];
byte c1, c2;
int l = str.Length - tail;
int s = step + 1;
for(int y = 0, x = offset; x < l; ++y, x += s) {
c1 = (byte)str[x];
if(c1 > 0x60) c1 -= 0x57;
else if(c1 > 0x40) c1 -= 0x37;
else c1 -= 0x30;
c2 = (byte)str[++x];
if(c2 > 0x60) c2 -= 0x57;
else if(c2 > 0x40) c2 -= 0x37;
else c2 -= 0x30;
b[y] = (byte)((c1 << 4) + c2);
}
return b;
}
}

在上面的速度测试中击败所有其他人:

===长串测试
BitConvertReplace计算Time Elapsed 2415 ms
. BitConvertReplace计算时间 StringBuilder计算Time Elapsed 5668 ms
LinqConcat计算时间流逝11826 ms
. LinqConcat计算时间流逝11826 ms
. LinqConcat计算时间流逝11826 ms LinqJoin计算Time Elapsed 9323 ms
.使用实例 LinqAgg计算Time Elapsed 7444 ms
.使用实例 ToHexTable calculation Time Elapsed 1028 ms
.使用实例 ToHexAcidzombie计算Time Elapsed 1035 ms
. sh ToHexPatrick计算时间流逝814毫秒
ToHexKurt计算Time Elapsed 1604 ms
ByteArrayToHexString计算Time Elapsed 1330 ms

. ByteArrayToHexString计算时间

===许多字符串测试
BitConvertReplace计算Time Elapsed 2238 ms
. BitConvertReplace计算时间 StringBuilder计算Time Elapsed 5393 ms
LinqConcat calculation Time Elapsed 9043 ms
.使用实例 LinqJoin计算Time Elapsed 9131 ms
.使用实例 LinqAgg计算Time Elapsed 7324 ms
.使用实例 ToHexTable calculation Time Elapsed 968 ms
.使用实例 ToHexAcidzombie calculation Time Elapsed 969 ms
. ToHexAcidzombie计算时间 ToHexPatrick计算时间流逝956毫秒
ToHexKurt计算Time Elapsed 1547 ms
ByteArrayToHexString计算Time Elapsed 1277 ms

. ByteArrayToHexString计算时间