关于C#:bitconverter.toString()的反向?

BitConverter.ToString() in reverse?

本问题已经有最佳答案,请猛点这里访问。

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

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

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

到现在为止,一直都还不错。有人知道我是怎么把这个放回阵列的吗?不存在需要字符串的bitconverter.getBytes()重载,将字符串分解为一个字符串数组,然后对每个字符串进行转换似乎是一个棘手的解决方案。

所讨论的数组可能是可变长度的,可能大约20个字节。


您可以自己分析字符串:

1
2
3
4
5
6
7
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])
   );
}

不过,我认为最新的解决方案是使用扩展:

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


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

1
2
3
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);

无拆分方法:(对字符串格式做了许多假设)

1
2
3
4
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);

还有一个方法,没有拆分或子字符串。但是,如果将此提交到源代码管理,则可能会被枪击。我对这种健康问题不负责任。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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转换)


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

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

base64也将大大缩短。

如果您需要使用这种格式,这显然没有帮助。


1
byte[] data = Array.ConvertAll<string, byte>(str.Split('-'), s => Convert.ToByte(s, 16));


我相信下面将有力地解决这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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;
}


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


it seems like a nasty workaround to break the string into an array of strings and then convert each of them.

我觉得没有别的办法…bitconverter.toString生成的格式非常具体,因此如果没有现有的方法将其解析回byte[],我想您必须自己做。