C# 中类似 Python 的字节数组字符串表示形式

问题描述 投票:0回答:2

这是我用来获取此字符串表示形式的方法:

    public static string ByteArrayToString(byte[] ba, string prefix)
    {
        StringBuilder hex = new StringBuilder(ba.Length * 2);
        foreach (byte b in ba)
        {
            if (prefix != null)
            {
                hex.Append(prefix);
            }
            hex.AppendFormat("{0:x2}", b);
        }
        return hex.ToString();
    }

这是字节数组的示例字符串表示形式 (

ByteArrayToString(arr, "\\x")
):

\x00\x00\x00\x80\xca\x26\xff\x56\xbf\xbf\x49\x5b\x94\xed\x94\x6e\xbb\x7a\xd0\x9d
\xa0\x72\xe5\xd2\x96\x31\x85\x41\x78\x1c\xc9\x95\xaf\x79\x62\xc4\xc2\x8e\xa9\xaf
\x08\x22\xde\x22\x48\x65\xda\x1d\xca\x12\x99\x42\xb3\x56\xa7\x99\xca\x27\x7b\x2b
\x45\x77\x14\x5b\xe1\x75\x04\x3d\xdb\x68\x45\x46\x72\x61\x20\xa9\xa2\xd9\x50\xd0
\x63\x9b\x4e\x7b\xa4\xa4\x48\xd7\xa9\x01\xd1\x8a\x69\x78\x6c\x79\xa8\x84\x39\x42
\x32\xb3\xb1\x1f\x04\x4d\x06\xca\x2c\xd5\xa0\x45\x8d\x10\x44\xd5\x73\xdf\x89\x0c
\x25\x1d\xcf\xfc\xb8\x07\x6b\x1f\xfa\xae\x67\xf9\x00\x00\x00\x03\x01\x00\x01

这是我想要的表示(这是Python的,忽略不同的换行符位置,这全部在一行上):

\x00\x00\x00\x80\xca&\xffV\xbf\xbfI[\x94\xed\x94n\xbbz\xd0\x9d\xa0r\xe5\xd2\x961
\x85Ax\x1c\xc9\x95\xafyb\xc4\xc2\x8e\xa9\xaf\x08"\xde"He\xda\x1d\xca\x12\x99B\xb
3V\xa7\x99\xca\'{+Ew\x14[\xe1u\x04=\xdbhEFra \xa9\xa2\xd9P\xd0c\x9bN{\xa4\xa4H\x
d7\xa9\x01\xd1\x8aixly\xa8\x849B2\xb3\xb1\x1f\x04M\x06\xca,\xd5\xa0E\x8d\x10D\xd
5s\xdf\x89\x0c%\x1d\xcf\xfc\xb8\x07k\x1f\xfa\xaeg\xf9\x00\x00\x00\x03\x01\x00\x0
1

Python 表示形式似乎将(十进制)32 和 126 之间的字节转换为其 ASCII 表示形式,而不是统一转义所有字节。如何让 C# 版本产生相同的字符串输出?我依赖于该字符串输出的哈希值,因此它们需要完全相同。

c# escaping arrays ascii
2个回答
3
投票

好吧,如果你确定编码的逻辑,那么你就可以实现它:

foreach (byte b in ba)
{
    if (b >= 32 && b <= 126)
    {
        hex.Append((char) b);
        continue;
    }

    ...

如果您正在寻找性能,您应该查看这个答案,并可能对其中列出的方法之一进行一些调整。


0
投票

马特的答案是正确的,并为我自己的使用指明了正确的方向,但有一些需要考虑的情况,我必须通过反复试验来弄清楚。

到目前为止,有 4 个字符需要转义为文字,而不是十六进制

字符串的最终格式可能会根据最终十六进制字符串中是否存在单引号和双引号而改变。

默认输出将字符串包装为 b'' 但是如果字符串包含单引号,并且没有双引号,则它会被包装为 b"" 。 如果字符串同时包含 ' 和 " ,则字符串中的所有单引号都将被转义并使用 b"" 。

示例

  • 默认:b'x\xc1o'
  • 单引号:b"x\xc1'o"
  • 存在单引号和双引号:b"x\xc1\'"o" 必须转义单引号
foreach (byte b in ba)
{
    if (b == 92) hex.Append("\\\\");
    if (b == 10) hex.Append("\\n");
    else if (b == 13) hex.Append("\\r");
    else if (b == 9) hex.Append("\\t");
    else if (b >= 32 && b <= 126)
    {
        hex.Append((char) b);
        continue;
    }
    else
    {
        hex.Append("\\x");
        hex.AppendFormat("{0:x2}", b);
    }
}

string hexformat = hex.ToString();

if (hexformat.Contains("'") && !hexformat.Contains("\""))
{
     hexformat = "b\"" + hexformat + "\"";
}
else if (hexformat.Contains("'") && hexformat.Contains("\""))
{
    hexformat = hexformat.Replace("'", "\\'");
    hexformat = "b\'" + hexformat + "'";
}
else
{
     hexformat = "b\'" + hexformat + "'";
}

// Could be optimized by checking the bytearray first for the presence of ' 
// and " instead of doing a Replace at the end.
© www.soinside.com 2019 - 2024. All rights reserved.