Redis keys are binary safe。我想乱用并使用C#将二进制文件放入redis。我选择的客户端不支持编写使用密钥的二进制密钥,这是有道理的。但是我只是在胡闹,所以告诉我如何才能做到这一点。
如何将原始字节[]转换为字符串?起初我正在考虑将byte []转换为utf8字符串,但unicode有一些检查是否有效。所以原始二进制文件应该失败。
其实我试了一下。而不是失败我得到一个奇怪的结果。我的主要问题是如何将原始byte[]
转换为等效字符串?因为将原始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
答案 0 :(得分:7)
如果你有一个任意字节[],那么将它作为一个字符串的方法是将它转换为十六进制或base-64之类的东西。最简单的是:
byte[] key = ...
string s = Convert.ToBase64String(key);
相反:
key = Convert.FromBase64String();
诱惑使用类似System.Text.Encoding的东西,但这完全不正确,并且不能用于进行强大的转换。如果使用编码,则存在两个问题:
这两个都不好!问题是使用是倒退的:编码将任意字符串转换为结构化字节[],从而允许对任何字符串进行编码/解码。 Base-64将任意byte []转换为结构化字符串。非常微妙的区别,但非常重要。
答案 1 :(得分:2)
您必须使用某种编码将字节转换为字符串。编码 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的字节,所以它们只是编码为?
,并且也会返回一个字节。