有时字节数组b64是UTF-8,有时是UTF-16。我一直在网上阅读 C# 字符串始终是 UTF-16,但我这里不是这种情况。为什么会发生这种情况,我该如何解决?我有一个将 base64 字符串转换为普通字符串的简单方法:
public static string FromBase64(this string input)
{
String corrected = new string(input.ToCharArray());
byte[] b64 = Convert.FromBase64String(corrected);
if (b64[1] == 0)
{
return System.Text.Encoding.Unicode.GetString(b64);
}
else
{
return System.Text.Encoding.UTF8.GetString(b64);
}
}
同样的事情发生在我的 base 64 编码器上:
public static string ToBase64(this string input)
{
String b64 = Convert.ToBase64String(input.GetBytes());
return b64;
}
public static byte[] GetBytes(this string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
例子: 在我的电脑上,“cABhAHMAcwB3AG8AcgBkADEA”解码为:
'p','\0','a','\0','s','\0','s','\0','w','\0','o','\0','r','\0','d','\0','1','\0'
但是在我同事的电脑上是:
'p','a','s','s','w','o','r','d','1'
编辑:
我知道我创建的字符串来自文本框,并且我保存它的文件始终是 UTF-8,所以所有内容都指向导致我的编码切换的 Convert 方法。
更新:
进一步深入研究后,我的同事似乎在他的代码版本中注释了一行非常重要的代码,即将从文件读取的值保存到哈希表中的那一行。我使用的默认值是 UTF-8 base64 值,因此我要将默认值更正为 utf-16 值,然后我可以清理代码,删除任何 UTF8 引用。
此外,我一直天真地使用从网站检索到的 UTF-8 base64 编码,却没有意识到自己陷入了什么境地。有趣的是,如果我的同事没有评论保存文件值的行,我永远不会发现这个事实。
代码的最终版本:
public static string FromBase64(this string input)
{
byte[] b64 = Convert.FromBase64String(input);
return System.Text.Encoding.Unicode.GetString(b64);
}
public static string ToBase64(this string input)
{
String b64 = Convert.ToBase64String(input.GetBytes());
return b64;
}
public static byte[] GetBytes(this string str)
{
return System.Text.Encoding.Unicode.GetBytes(str);
}
最佳答案
首先我要揭穿题名:
Convert.FromBase64String()
returns Unicode sometimes, or UTF-8
事实并非如此。然后提供相同的输入,有效的 base64 编码文本,Convert.FromBase64String()
总是返回相同的输出。
继续前进,您无法仅通过检查有效负载来明确确定用于字符串的编码。你试图用
if (b64[1] == 0)
// encoding must be UTF-16
事实并非如此。绝大多数 UTF-16 字符元素都无法通过该测试。无论您如何尝试编写此测试都注定要失败。这是因为当解释为不同的编码时,存在定义明确的字符串的字节数组。换句话说,例如,可以构造在被视为 UTF-8 或 UTF-16 时有效的字节数组。
因此,您必须先验地知道有效负载是编码为 UTF-16、UTF-8 还是其他编码。
解决方案是在 base64 编码之前跟踪原始编码。将该信息与 base64 编码的有效负载一起传递。然后在解码时,您可以确定使用哪种 Encoding
解码回字符串。
在我看来,您的字符串全部来自 UTF-16 .net 字符串。在这种情况下,您永远不会有 UTF-8 字符串,并且应该始终使用 UTF-16
进行解码。那就是你使用 Encoding.Unicode.GetString()
。
此外,您代码中的 GetBytes
方法很差。应该是:
public static byte[] GetBytes(this string str)
{
return Encoding.Unicode.GetBytes(str);
}
另一个奇怪的地方:
String corrected = new string(input.ToCharArray());
这是一个空操作。
最后,当编码为 UTF-8 时,您的文本很可能会更紧凑。因此,也许您应该考虑在应用 base64 编码之前这样做。
关于您的更新,您所说的不正确。这段代码:
string str = Encoding.Unicode.GetString(
Convert.FromBase64String("cABhAHMAcwB3AG8AcgBkADEA"));
将 password1
分配给 str
,无论它在哪里运行。
关于c# - Convert.FromBase64String 有时返回 unicode,或 UTF-8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21269900/