5

Redis 密钥是二进制安全的。我想搞砸并使用 C# 将二进制文件放入 redis。我选择的客户不支持编写二进制密钥,它使用密钥,这很有意义。但是我只是在鬼混,所以告诉我我该怎么做。

如何将原始字节 [] 转换为字符串?起初我正在考虑将 byte[] 转换为 utf8 字符串,但是 unicode 有一些检查来查看它是否有效。所以原始二进制文件应该失败。

其实我试过了。我没有失败,而是得到了一个奇怪的结果。我的主要问题是如何将原始字符串转换byte[]为等效字符串?就像将原始字节 [] 作为字符串而不是编码为 base32/64/hex/whatever 一样。我不重要的问题是为什么我得到一个 512 字节的字符串而不是一个异常说这不是一个有效的 UTF8 字符串?

代码

var rainbow = new byte[256];
for (int i = 0; i < 256; i++)
{
    rainbow[i] = (byte)i;
}
var sz = Encoding.UTF8.GetString(rainbow);
var szarr = Encoding.UTF8.GetBytes(sz);
Console.WriteLine("{0} {1} {2}", ByteArraysEqual(szarr, rainbow), szarr.Length, rainbow.Length);

输出

假 512 256

4

2 回答 2

8

如果您有任意字节 [],将其作为字符串获取的方法是将其转换为 hex 或 base-64 之类的东西。最简单的:

byte[] key = ...
string s = Convert.ToBase64String(key);

反过来:

key = Convert.FromBase64String();

使用 System.Text.Encoding 之类的东西很诱人,但这是完全不正确的,并且不能用于进行可靠的转换。如果使用Encoding,有两个问题:

  • 许多键无法成功往返
  • 许多不同的 byte[] 键可以成为相同的字符串键

这两个都不好!问题是使用是向后的:编码将任意字符串转换为结构化字节[],允许对任何字符串进行编码/解码。Base-64 将任意 byte[] 转换为结构化字符串/从结构化字符串转换。非常微妙的区别,但非常重要。

于 2012-09-02T05:54:12.537 回答
4

您必须使用某种编码将字节转换为字符串。编码iso-8859-1将给出正确的结果:

var sz = Encoding.GetEncoding("iso-8859-1").GetString(rainbow);
var szarr = Encoding.GetEncoding("iso-8859-1").GetBytes(sz);
Console.WriteLine("{0} {1} {2}", ByteArraysEqual(szarr, rainbow), szarr.Length, rainbow.Length);

真 256 256

问题是 UTF8 每个字符需要一个以上的字节。它可以用一个字节编码前 128 个字符:

Console.Write(Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(new byte[] { 127 })).Length);

1

但其余的需要三个字节:

Console.Write(Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(new byte[] { 128 })).Length);

3

因此,当您将字节 0-255 转换为字符串并使用 UTF8 返回时,前 128 个作为一个字节返回,但最后 128 个返回为 3. 128 + 3*128 = 512,因此是您的结果。

ASCII 不知道如何处理超过 128 的字节,因此它们只是被编码为?,并且也作为一个字节返回。

于 2012-09-02T03:52:42.090 回答