如何将byte[]转换为string?每次尝试时,都会得到


System.Byte []


而不是值。

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

评论

“每次尝试时”,您听起来好像都会真正起作用。

合理地假设提问者尝试了不同的方法

#1 楼

为此,有一个内置方法:

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(..)

– ala
09年7月28日在12:25

以防万一,对于Windows 8 / Windows Phone 8.1,有一个CryptographicBuffer.EncodeToHexString用于不带破折号的情况。

–七十
2014年11月13日在18:48



@Grungondola:听起来很奇怪,将字节转换为字符串的所有其他方式会慢得多。您不是使用+ =将字符串连接在一起,是吗?

–古法
15年11月23日在22:29

@Grungondola:这很可能是表现不佳的原因。如果在循环中使用+ =,则在非常短的循环中效果很好,但是扩展性很差。每增加一次迭代,执行时间就会大约增加一倍,因此在大约20次迭代中,您会遇到性能问题。每增加10次迭代,循环将花费大约1000倍的时间。

–古法
15年11月24日在16:19

[允许BitConverter.ToString格式不包含破折号·问题#519·dotnet / corefx](github.com/dotnet/corefx/issues/519)

–lindexi
19年3月18日在8:00

#2 楼

我以为我会比较这里列出的每种方法的速度。我基于此进行了速度测试代码。

结果是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构建数组的Concat

LinqJoin = mloskot,字符串回答。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 ms(内置/简单最快)
StringBuilder计算已用时间75,723毫秒(StringBuilder不重新分配)
LinqConcat计算已用时间182,094 ms
LinqJoin计算已用时间181,142 ms
LinqAgg计算所用时间93,087 ms(具有重新分配的StringBuilder)
ToHex计算所用时间19,167 ms(最快)

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

BitConvertReplace计算已用时间3431 ms
StringBuilder计算已用时间8289 ms
LinqConcat计算已用时间21512 ms
LinqJoin计算所用的时间19433 ms
LinqAgg计算所用的时间9230 ms
ToHex计算所用时间1976 ms

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

BitConvertReplace计算时间25,680 ms
StringBuilder计算已用时间78,411 ms
LinqConcat计算已用时间101,233 ms
LinqJoin计算已用时间99,311 ms
LinqAgg计算已用时间84,660 ms
ToHex计算已用时间18,221 ms

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


BitConvertReplace计算已用时间1347 ms
StringBuilder计算已用时间3234 ms
LinqConcat计算已用时间5013 ms
LinqJoin计算已用时间4826 ms
LinqAgg计算已用时间3589 ms
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();
}


也用类似的方法回答,我还没有比较我们的结果。

评论


好的答案,但是您的代码中的一行让我感到恼火。为什么使用十六进制值而不是char?你为什么不这样做(char)(b> 9?b-10 +'A':b +'0'); <-通过将'A'转换为'a'也更容易将大写更改为小写

–user34537
2012年4月6日在22:22



老实说,我只是复制了Kurt's Answer的那一部分,甚至没有费心弄清楚当时的工作方式...

–胸腺嘧啶
2012年4月9日在16:44

更好的性能:“ 0123456789ABCDEF” [b]

–乔纳森·吉尔伯特(Jonathan Gilbert)
17年1月13日在16:21

@JonathanGilbert看起来像上面的ByteArrayToHexString方法的不完整版本,我的摘要为提高速度建议

–胸腺嘧啶
17年1月16日在19:14



哦,您是对的,出于某种原因,我没有看到该变体。不知道我怎么想念它。 :-)

–乔纳森·吉尔伯特(Jonathan Gilbert)
17年1月16日在20:43

#3 楼

十六进制,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及更高版本上,string.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之前的版本中,string.Concat具有10个重载函数,在4.0上现在为12

评论


迈克尔(Michael),您在Select上需要一个.ToArray(),否则(如图所示),您将得到一个{System.Linq.Enumerable.WhereSelectArrayIterator },该字符串将String.Join强制转换为String []。

–澳大利亚Craig
09年3月8日在6:17

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

–汤玛斯·林哈特(TomášLinhart)
2010年8月25日在17:03

@AussieCraig您只需要.NET 4.0之前的ToArray。 at-Michael我认为string.Concat(从ba中的b选择b.ToString(“ X2”))甚至更漂亮-您可以使用它依赖于.NET 4.0 String的条件在第二行中对其进行编辑.Concat(IEnumerable )重载?

– Ruben Bartelink
13年5月8日在11:44

#4 楼

这是另一种方法:

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

评论


使用StringBuilder结果=新的StringBuilder(Bytes.Length * 2);使我的测试更快

–胸腺嘧啶
2012年4月9日在17:24

有人可以解释一下HexValue数组中0x09和0x0A之间的额外0x00吗?提前致谢!

–网络僧侣
2013年12月13日在17:43

额外的0x00基于从'9'到'A'的距离。如果您在Windows(或任何与您的平台等效的平台)上运行charmap,您将看到之间有7个字符。因此,7 0x00。

–乔尔
2014年7月9日14:57

如果我想以十六进制值形式返回字节数组怎么办?

–库什
20年8月24日在12:24

#5 楼

我喜欢将扩展方法用于这种转换,即使它们只是包装标准库方法也是如此。对于十六进制转换,我使用以下手动调整(即快速)算法:

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


#6 楼

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

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

string hexString = sb.ToString();


评论


看起来不错。这确实看起来应该是框架中的内容,我发誓人们一直在寻找一种内置的方式来执行此操作。不知道为什么还没有东西。那好吧。

– TJB
09年3月8日在5:39

在BitConverter类中,有内置的方法可以执行此操作。

–古法
09年3月8日在6:59

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

–古法
09年3月8日在7:17

#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<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();
    }
}


评论


如果您需要减少执行时间,那就是您要使用的方式,但是要考虑到增加启动时间和分配5-6 KB数据的代价。

–古法
2013年9月2日在18:04

@Guffa:从内存来看,这很重要,因为它不是一次执行2个字母,而是在所有情况下都很快,但是这个解决方案似乎比其他解决方案要快得多。我会提供实际数字,但是我不记得他们了,也不知道我将考试保存到什么地方

–user34537
2013年9月3日在6:58



#8 楼

非常快速的扩展方法(带反转):
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 ms
ToHexKurt计算时间已过1604 ms
ByteArrayToHexString计算时间已过1330 ms
===很多字符串测试
BitConvertReplace计算已用时间2238 ms
StringBuilder计算已用时间5393 ms
LinqConcat计算已用时间9043 ms
LinqJoin计算已用时间9131 ms
LinqAgg计算已用时间7324 ms
ToHexTable计算已用时间968 ms
ToHexAcidzombie计算时间969 ms
ToHexPatrick计算时间956 ms
ToHexKurt计算时间1547 ms
ByteArrayToHexString计算时间1277 ms


评论


[d >> 4],[d&0xf]快于[d / 0x10],[d%0x10]

– Palota
15年11月23日在17:18

注意。也可以使用默认参数值而不是重载进行改进。不幸的是,我现在没有时间重新运行速度测试。

–帕特里克(Patrick)
2015年11月25日14:34

ToHex的prefix参数只是使该字符串包含在结果之前,对吗?我很好奇为什么,调用者进行串联似乎同样容易。也许它可以保存分配?

–弗兰克·施维特曼(Frank Schwieterman)
16-3-28在21:37



可以通过使用新的Span 进一步加快速度吗?

–亚当骑士
18-09-27在14:39

#9 楼

只是为了给堆增加一个答案,我使用了一个System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary类,该类可以将字节与十六进制进行转换:

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


不确定如何比较(基准)与其他实现,但是IMO非常简单-尤其是从十六进制转换回字节时。

#10 楼

使用:

 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

#11 楼

您必须知道以字节表示的字符串的编码,但是您可以说System.Text.UTF8Encoding.GetString(bytes)System.Text.ASCIIEncoding.GetString(bytes)。 (我是从内存中执行此操作的,因此API可能并不完全正确,但它非常接近。)

有关第二个问题的答案,请参见此问题。

#12 楼

您将LINQ与字符串方法结合使用:

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


评论


这可以通过使用string.Concat()并删除.ToArray()来简化。

–罗尼·奥弗比(Ronnie Overby)
2015年2月27日在16:44

通过字符串插值可以更小:$“ {bin:X2}” :)

–帕特里克(Patrick)
18/12/18在16:58

#13 楼

这是字节数组(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" }));
        }
    }
}


评论


绝对可以在性能和可读性之间进行权衡,但是一次查找两个字符是一个明智的优化。不知道为什么至少有两个人认为需要对此进行否决-如果您的目标是可读性,这不是答案,但是如果您需要每秒计算兆字节的十六进制字符串,那肯定是!

–乔纳森·吉尔伯特(Jonathan Gilbert)
17年1月13日在16:24

#14 楼

这里没有人提到为什么要获取“ System.Byte []”字符串而不是值的原因,所以我会这样做。

将对象隐式转换为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()的值。

评论


我应该说“ System.Byte [] ToString(string)似乎不给我十六进制字符串”。我忘记了ToString是虚拟的。这是一个老问题

–user34537
2013年9月2日13:36



#15 楼

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

Jon Skeet撰写了一篇有关.NET中编码和unicode的不错的文章。 。推荐阅读。

#16 楼

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

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

看起来可能没有太大的区别,但速度仍然更快:)

#17 楼

我不确定您是否需要执行此操作,但这是将byte []转换为我可以想到的十六进制字符串的最快方法:

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


#18 楼

用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();


评论


下选民想解释他们的问题吗?

–马修·怀特(Matthew Whited)
11年5月24日在20:06

并没有对此投票,但是sb.Append(“ X2”)对我来说似乎是错误的。您不使用'v'lambda参数。

–戴夫·范·登·艾恩德
2011年7月8日在9:00

很好...当您在文本框中直接输入示例时,就会发生这种情况。固定-谢谢

–马修·怀特(Matthew Whited)
2011年7月8日在9:41



我宁愿使用AppendFormat(),但这更像是挑剔。

–戴夫·范·登·艾恩德
2011年7月8日在17:46

#19 楼

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