当前位置:  开发笔记 > 编程语言 > 正文

byte []到十六进制字符串

如何解决《byte[]到十六进制字符串》经验,为你挑选了9个好方法。

如何将a转换byte[]string?我每次尝试都会得到

System.Byte []

而不是价值.

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



1> Guffa..:

有一个内置的方法:

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


没关系,我想我发现它是Convert.FromBase64String(..)
@Grungondola:这很可能是性能不佳的原因.如果在循环中使用`+ =`,它适用于非常短的循环,但它的扩展非常糟糕.每增加一次迭代大约会使执行时间加倍,因此在大约20次迭代时,您会遇到性能问题.每增加10次迭代,循环时间就会延长1000倍.
@Grungondola:将字节转换为字符串的所有其他方式都会慢得多,这听起来很奇怪.您没有使用`+ =`将字符串连接在一起,是吗?

2> Thymine..:

我以为我会尝试比较这里列出的每种方法的速度. 我根据这个速度测试代码.

结果是BitConverter + String.Replace似乎比大多数其他简单方法更快.但是使用像Nathan Moinvaziri的ByteArrayToHexString或Kurt的ToHex 这样的算法可以提高速度.

我还发现有趣的是string.Concat和string.Join比长字符串的StringBuilder实现慢得多,但对于较短的数组则类似.可能是因为在较长的字符串上扩展StringBuilder,所以设置初始大小应该否定这种差异.

从这里的答案中获取每一段代码:

BitConvertRep =通过Guffa,BitConverter和String.Replace回答(我建议大多数情况下使用)

StringBuilder = Quintin Robinson的回答,foreach char StringBuilder.Append

LinqConcat =由Michael Buen回答,Linq构建数组的string.Concat

LinqJoin =通过mloskot,string.Join of Linq建立数组

LinqAgg =答案:Matthew Whited,IEnumerable.Aggregate with StringBuilder

ToHex =由Kurt回答,在数组中设置字符,使用字节值来获取十六进制

ByteArrayToHexString = Nathan Moinvaziri的答案,与上面的ToHex大致相同,可能更容易阅读(我推荐速度)

ToHexFromTable =在Nathan Moinvaziri的回答中链接,对我而言,这与上面的2速度接近,但需要一个256个字符串的数组才能始终存在

附: LONG_STRING_LENGTH = 1000 * 1024;

BitConvertRep计算时间经过27,202毫秒(内置最快/简单)

StringBuilder计算时间经过75,723毫秒(StringBuilder没有重新分配)

LinqConcat计算时间经过了182,094毫秒

LinqJoin计算时间累计181,142毫秒

LinqAgg计算时间耗时93,087毫秒(带重新分配的StringBuilder)

ToHex计算时间耗时19,167毫秒(最快)

用:LONG_STRING_LENGTH = 100 * 1024;,类似的结果

BitConvertReplace计算时间经过3431 ms

StringBuilder计算时间经过8289毫秒

LinqConcat计算时间经过21512毫秒

LinqJoin计算时间耗时19433毫秒

LinqAgg计算时间经过9230毫秒

ToHex计算时间经过了1976毫秒

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

BitConvertReplace计算时间经过25,680 ms

StringBuilder计算时间经过78,411毫秒

LinqConcat计算时间经过101,233毫秒

LinqJoin计算时间经历了99,311毫秒

LinqAgg计算时间耗时84,660毫秒

ToHex计算时间经过18,221毫秒

附: int MANY_STRING_COUNT = 2000; int MANY_STRING_LENGTH = 20;

BitConvertReplace计算时间经过1347 ms

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 manyString = new List(MANY_STRING_COUNT);
    for (int i = 0; i < MANY_STRING_COUNT; ++i)
    {
        manyString.Add(GetRandomBytes(MANY_STRING_LENGTH));
    }

    var algorithms = new Dictionary>();
    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();
}

还有一个类似过程的另一个答案,我还没有比较我们的结果.



3> Michael Buen..:

Hex,Linq-fu:

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

与时俱进

正如@RubenBartelink所指出的那样,没有转换为IEnumerable数组的代码: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+c__Iterator10`2[System.Byte,System.String]
010204081020

在.NET 4.0以上,string.Concat有一个接受IEnumerable的重载.因此在4.0上,上述代码对于变量s和t都具有相同的输出

010204081020
010204081020

在4.0之前,ba.Select(b => b.ToString("X2"))进入过载(object arg0),IEnumerable进入正确的重载的方式,即(params string[] values),我们需要转换IEnumerable为字符串数组.在4.0之前,string.Concat有10个重载函数,在4.0上它现在是12


您可以使用Concat更干净的解决方案.String.Concat(ba.Select(b => b.ToString("X2"))

4> Nathan Moinv..:

这是另一种方法:

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



5> Quintin Robi..:

好吧,我不经常将字节转换为十六进制,所以我不得不说我不知道​​是否有更好的方法,但这是一种方法来做到这一点.

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

string hexString = sb.ToString();


将StringBuilder的容量指定为myByteArray.Length*2,以便在循环期间不必重新分配.

6> kgriffs..:

我喜欢使用扩展方法进行这样的转换,即使它们只是包装标准库方法.在十六进制转换的情况下,我使用以下手动调整(即快速)算法:

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;
}



7> 小智..:

我想我应该提供一个答案.从我的测试来看,这种方法是最快的

public static class Helper
{
    public static string[] HexTbl = Enumerable.Range(0, 256).Select(v => v.ToString("X2")).ToArray();
    public static string ToHex(this IEnumerable 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();
    }
}



8> Patrick..:

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

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计算时间经过2415 ms
StringBuilder计算时间经过5668 ms
LinqConcat计算时间经过11826 ms
LinqJoin计算时间经过9323 ms
LinqAgg计算时间经过7444 ms
ToHexTable计算时间经过1028 ms
ToHexAcidzombie计算时间经过1035 ms
ToHexPatrick计算耗时814毫秒
ToHexKurt计算时间耗时1604毫秒
ByteArrayToHexString计算时间耗时1330毫秒

===许多字符串测试
BitConvertReplace计算时间经过2238 ms
StringBuilder计算时间经过5393 ms
LinqConcat计算时间经过9043 ms
LinqJoin计算时间经过9131 ms
LinqAgg计算时间经过7324 ms
ToHexTable计算时间经过968 ms
ToHexAcidzombie计算时间经过969 ms
ToHexPatrick计算经过的时间956毫秒
ToHexKurt计算时间经过1547毫秒
ByteArrayToHexString计算时间经过1277毫秒


[d >> 4],[d&0xf]快于[d/0x10],[d%0x10]
那是正确的.

9> Allan..:

只是为了添加一个答案,有一个System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary我用过的类可以将字节转换为十六进制和从十六进制转换:

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

不确定它与其他实现的比较(基准),但IMO非常简单 - 特别是从十六进制转换回字节.

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有