【问题标题】:BitConverter.ToString() in reverse? [duplicate]BitConverter.ToString() 反向? [复制]
【发布时间】:2010-11-16 20:22:33
【问题描述】:

我有一个字节数组,我想将其存储为字符串。我可以这样做:

byte[] array = new byte[] { 0x01, 0x02, 0x03, 0x04 };
string s = System.BitConverter.ToString(array);

// Result: s = "01-02-03-04"

到目前为止一切顺利。有谁知道我如何将它恢复到数组中?没有接受字符串的 BitConverter.GetBytes() 重载,将字符串分解为字符串数组然后转换每个字符串似乎是一种讨厌的解决方法。

有问题的数组可能是可变长度的,大概是 20 个字节。

【问题讨论】:

  • 您要么使用拆分,要么编写一个非常具体的拆分实现...只需使用拆分。

标签: c# .net


【解决方案1】:
byte[] data = Array.ConvertAll<string, byte>(str.Split('-'), s => Convert.ToByte(s, 16));

【讨论】:

  • 想解释一下这段代码的作用吗?单线很好,但通常会发生很多事情才能达到所需的结果。
  • 这只是 CoderTao 答案的简短版本。它用“Array.ConvertAll”方法替换了字节数组构造函数和“for”循环。它使用 lambda 表达式将每个 HEX 字符串转换为一个字节。我在想这是不言自明的。
【解决方案2】:

你可以自己解析字符串:

byte[] data = new byte[(s.Length + 1) / 3];
for (int i = 0; i < data.Length; i++) {
   data[i] = (byte)(
      "0123456789ABCDEF".IndexOf(s[i * 3]) * 16 +
      "0123456789ABCDEF".IndexOf(s[i * 3 + 1])
   );
}

不过,我相信最简洁的解决方案是使用扩展:

byte[] data = s.Split('-').Select(b => Convert.ToByte(b, 16)).ToArray();

【讨论】:

  • 我对您的 LINQ 解决方案投了赞成票,但对于“低技术”解决方案却出现了编译时错误。需要一组额外的括号,但它很容易解决。 (byte)("0123456789ABCDEF".IndexOf(s[i * 3]) * 16 + "0123456789ABCDEF".IndexOf(s[i * 3 + 1]))
  • @dana:是的,你是对的,它需要另一个括号。很好的收获。
  • Lambda/Extensions 解决方案非常优雅!谢谢!
【解决方案3】:

ToString 方法并不是真正的转换,而是为调试、轻松打印等提供人类可读的格式。
我会重新考虑 byte[] - String - byte[] 要求,可能更喜欢 SLaks 的 Base64 解决方案

【讨论】:

    【解决方案4】:

    如果您不需要该特定格式,请尝试使用Base64,如下所示:

    var bytes = new byte[] { 0x12, 0x34, 0x56 };
    var base64 = Convert.ToBase64String(bytes);
    bytes = Convert.FromBase64String(base64);
    

    Base64 也将大大缩短。

    如果您需要使用该格式,这显然无济于事。

    【讨论】:

    • 我所需要的很好的答案
    • 比BitConverter好很多。谢谢。
    • 当场谢谢
    【解决方案5】:

    我相信以下内容将有力地解决这个问题。

    public static byte[] HexStringToBytes(string s)
    {
        const string HEX_CHARS = "0123456789ABCDEF";
    
        if (s.Length == 0)
            return new byte[0];
    
        if ((s.Length + 1) % 3 != 0)
            throw new FormatException();
    
        byte[] bytes = new byte[(s.Length + 1) / 3];
    
        int state = 0; // 0 = expect first digit, 1 = expect second digit, 2 = expect hyphen
        int currentByte = 0;
        int x;
        int value = 0;
    
        foreach (char c in s)
        {
            switch (state)
            {
                case 0:
                    x = HEX_CHARS.IndexOf(Char.ToUpperInvariant(c));
                    if (x == -1)
                        throw new FormatException();
                    value = x << 4;
                    state = 1;
                    break;
                case 1:
                    x = HEX_CHARS.IndexOf(Char.ToUpperInvariant(c));
                    if (x == -1)
                        throw new FormatException();
                    bytes[currentByte++] = (byte)(value + x);
                    state = 2;
                    break;
                case 2:
                    if (c != '-')
                        throw new FormatException();
                    state = 0;
                    break;
            }
        }
    
        return bytes;
    }
    

    【讨论】:

    • 你是对的,虽然我很确定数据的格式是正确的(在任何一种情况下都会引发异常),我可能会选择 Split 版本或 Linq 版本 -特别是因为它节省了大约 40 行代码。
    【解决方案6】:

    不是内置方法,而是实现。 (不过,它可以在没有拆分的情况下完成)。

    String[] arr=str.Split('-');
    byte[] array=new byte[arr.Length];
    for(int i=0; i<arr.Length; i++) array[i]=Convert.ToByte(arr[i],16);
    

    没有拆分的方法:(对字符串格式做了很多假设)

    int length=(s.Length+1)/3;
    byte[] arr1=new byte[length];
    for (int i = 0; i < length; i++)
        arr1[i] = Convert.ToByte(s.Substring(3 * i, 2), 16);
    

    还有一种方法,没有拆分或子字符串。但是,如果您将其提交给源代码控制,您可能会被枪杀。我对此类健康问题不承担任何责任。

    int length=(s.Length+1)/3;
    byte[] arr1=new byte[length];
    for (int i = 0; i < length; i++)
    {
        char sixteen = s[3 * i];
        if (sixteen > '9') sixteen = (char)(sixteen - 'A' + 10);
        else sixteen -= '0';
    
        char ones = s[3 * i + 1];
        if (ones > '9') ones = (char)(ones - 'A' + 10);
        else ones -= '0';
    
        arr1[i] = (byte)(16*sixteen+ones);
    }
    

    (基本上是在两个字符上实现base16转换)

    【讨论】:

    • 是的,它可能归结为这一点。我希望有一种我在某处遗漏的方法 - 不在某处烘烤它似乎很奇怪......
    • “虽然没有拆分也可以做到”:如何?
    • 嗯...我认为拆分版本更整洁,可能更快(以其中一种极小的方式)
    • Split 版本并不快。 Split 必须为其返回分配一个数组,如果字符串很大,它可能会很慢。对于大字符串,循环遍历字符串中的字符会更快。
    • 公平通话。不过,打字速度更快.. :)
    【解决方案7】:

    将字符串分解为字符串数组然后转换每个字符串似乎是一种令人讨厌的解决方法。

    我不认为还有其他方法... BitConverter.ToString 生成的格式非常具体,所以如果没有现有的方法可以将其解析回字节[],我想你必须自己做

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 2017-07-20
      • 1970-01-01
      • 1970-01-01
      • 2019-11-09
      • 2012-10-05
      相关资源
      最近更新 更多