【问题标题】:byte[] to hex string [duplicate]字节 [] 到十六进制字符串 [重复]
【发布时间】:2012-09-25 06:10:27
【问题描述】:

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

System.Byte[]

而不是值。

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

【问题讨论】:

  • “每次我尝试它”你听起来像一段时间它可能真的有效。
  • 有理由假设提问者尝试了不同的方法

标签: c# string hex


【解决方案1】:

这是另一种方法:

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 Result = new StringBuilder(Bytes.Length * 2); 在我的测试中稍微加快了速度
  • 有人能解释一下HexValue数组中0x09和0x0A之间多余的0x00吗?提前致谢!
  • 额外的 0x00 是基于从 '9' 到 'A' 的距离。如果您在 Windows(或任何与您的平台等效的平台)上运行 charmap,您会看到两者之间有 7 个字符。因此,7 0x00。
  • 如果我想以字节数组形式返回十六进制值怎么办?
【解决方案2】:

有一个内置的方法:

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(..)
  • 以防万一,对于 Windows 8/Windows Phone 8.1,有一个 CryptographicBuffer.EncodeToHexString 表示没有破折号的情况。
  • @Grungondola:听起来很奇怪,所有其他将字节转换为字符串的方法都会慢得多。您没有使用+= 将字符串连接在一起,是吗?
  • @Grungondola:这很可能是性能不佳的原因。如果您在循环中使用+=,它适用于非常短的循环,但它的扩展性非常差。每次额外的迭代大约会使执行时间加倍,因此在大约 20 次迭代时,您会遇到性能问题。每增加 10 次迭代将使循环花费大约 1000 倍。
  • [允许 BitConverter.ToString 格式不带破折号 · 问题 #519 · dotnet/corefx](github.com/dotnet/corefx/issues/519)
【解决方案3】:

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

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

=== 多串测试
BitConvertReplace 计算耗时 2238 毫秒
StringBuilder 计算耗时 5393 毫秒
LinqConcat 计算耗时 9043 毫秒
LinqJoin 计算耗时 9131 毫秒
LinqAgg 计算耗时 7324 毫秒
ToHexTable 计算耗时 968 毫秒
ToHexAcidzombie 计算耗时 969 毫秒
ToHexPatrick 计算耗时 956 毫秒
ToHexKurt 计算耗时 1547 毫秒
ByteArrayToHexString 计算耗时 1277 ms

【讨论】:

  • [d >> 4], [d & 0xf] 比 [d / 0x10], [d % 0x10] 快
  • 注明。也可以使用默认参数值而不是重载来改进它。不幸的是,我现在没有时间重新运行速度测试。
  • ToHex 的前缀参数只是导致该字符串包含在结果之前,对吗?我很好奇为什么,调用者进行连接似乎同样容易。也许是为了保存分配?
  • 能否通过使用新的 Span 进一步加快速度?
【解决方案4】:

我不确定您是否需要执行此操作,但这是我能想到的将 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);
}

【讨论】:

    【解决方案5】:

    我想我应该提供一个答案。根据我的测试,这种方法是最快的

    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 数据的代价。
    • @Guffa:从记忆来看,这很重要,因为它不是一次附加一个字母,而是执行 2 个。但无论如何,所有解决方案都很快,但这个解决方案似乎比其他解决方案快得多。我会给出实际数字,但我不记得它们,也不记得我保存测试的位置
    【解决方案6】:

    这里没有人提到你得到“System.Byte[]”字符串而不是值的原因,所以我会。

    当一个对象被隐式转换为字符串时,程序将默认使用该对象的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 是虚拟的。这是一个老问题
    【解决方案7】:

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

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

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

    【讨论】:

      【解决方案8】:

      Hex,Linq-fu:

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

      与时俱进

      正如@RubenBartelink 所指出的,没有将IEnumerable&lt;string&gt; 转换为数组的代码:ba.Select(b =&gt; 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 =&gt; b.ToString("X2")) 去重载(object arg0)IEnumerable&lt;string&gt; 去适当的重载,即(params string[] values),我们需要将IEnumerable&lt;string&gt; 转换为字符串数组。在 4.0 之前,string.Concat 有 10 个重载函数,在 4.0 上现在是 12 个

      【讨论】:

      • Michael,您需要在 Select 上使用 .ToArray(),否则(如图所示)您会得到一个 {System.Linq.Enumerable.WhereSelectArrayIterator} String.Join 转换为字符串[].
      • Concat 可以使用更干净的解决方案。 String.Concat(ba.Select(b => b.ToString("X2"))
      • @AussieCraig 您只需要.NET 4.0 之前的 ToArray。 at-Michael 我认为string.Concat(from b in ba select b.ToString("X2")) 更漂亮 - 是否有机会将其作为第二行进行编辑,前提是它依赖于 .NET 4.0 String.Concat(IEnumerable&lt;string&gt;) 过载?
      【解决方案9】:

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

      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 毫秒 ToHEx = 12168ms

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

      【讨论】:

        【解决方案10】:
        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);
        }
        

        【讨论】:

          【解决方案11】:

          我想我会尝试比较一下这里列出的每种方法的速度。 I based the speed testing code off this.

          结果是 BitConverter+String.Replace 似乎比大多数其他简单方法更快。但是可以使用 Nathan Moinvaziri's 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 的 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 ms(最快)

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

          • BitConvertReplace 计算耗时 3431 毫秒
          • StringBuilder 计算耗时 8289 毫秒
          • LinqConcat 计算耗时 21512 毫秒
          • LinqJoin 计算耗时 19433 毫秒
          • LinqAgg 计算耗时 9230 毫秒
          • ToHex 计算耗时 1976 毫秒

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

          • BitConvertReplace 计算耗时 25,680 毫秒
          • 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 毫秒
          • 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();
          }
          

          Also another answer with a similar process,我还没有比较我们的结果。

          【讨论】:

          • 很好的答案,但是你的一行代码让我很生气。为什么使用十六进制值而不是字符?你为什么不这样做(char)(b &gt; 9 ? b - 10 + 'A' : b + '0');
          • 老实说,我只是从 Kurt's Answer 复制了那部分,甚至没有费心去弄清楚它当时是如何工作的......
          • 更好的性能:"0123456789ABCDEF"[b]
          • @JonathanGilbert 看起来像上面的方法 ByteArrayToHexString 的不完整版本,我的总结建议速度
          • 哦,你是对的,出于某种原因,我没有看到那个变体。不知道我是怎么错过的。 :-)
          【解决方案12】:

          与:

          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

          【讨论】:

            【解决方案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" }));
                    }
                }
            }
            

            【讨论】:

            • 这里肯定是在性能和​​可读性之间进行权衡,但是一次查找两个字符是一个聪明的优化。不知道为什么至少有两个人觉得有必要对此投反对票——如果您的目标是可读性,这不是答案,但如果您需要每秒计算兆字节的十六进制字符串,那肯定是!
            【解决方案14】:

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

            【讨论】:

            • 投反对票的人愿意解释他们的问题吗?
            • 没有对此投反对票,但 sb.Append("X2") 对我来说似乎是错误的。您不使用 'v' lambda 参数。
            • 很好...当您直接在文本框中输入示例时会发生这种情况。已修复-谢谢
            • 我宁愿使用 AppendFormat(),但这更像是吹毛求疵。
            【解决方案15】:

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

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

            【讨论】:

              【解决方案16】:

              你将 LINQ 与字符串方法结合起来:

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

              【讨论】:

              • 这可以通过使用string.Concat()和删除.ToArray()来简化
              • 可以通过字符串插值更小:$"{bin:X2}" :)
              【解决方案17】:

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

              Jon Skeet 有一个关于 .NET 中的编码和 unicode 的good article。推荐阅读。

              【讨论】:

                【解决方案18】:

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

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

                【讨论】:

                • 看起来差不多。这似乎真的应该在框架中,我发誓人们一直在寻找一种内置的方式来做到这一点。不知道为什么那里没有东西。哦,好吧。
                • 在 BitConverter 类中有一个内置的方法可以做到这一点。
                • 将 StringBuilder 的容量指定为 myByteArray.Length*2,这样它就不必在循环期间重新分配。
                【解决方案19】:

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

                关于第二个问题的答案,请参阅this question

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-11-30
                  • 2014-05-26
                  • 2015-01-17
                  • 2012-01-24
                  • 2016-12-27
                  • 1970-01-01
                  相关资源
                  最近更新 更多