我们最近遇到了一些来自供应商的示例代码,用于散列Web服务调用的密钥,他们的示例是在VB.NET中我们转换为C#。这导致散列产生不同的输入。事实证明,他们生成加密密钥的方式是将char数组转换为字符串并返回字节数组。这让我发现VB.NET和C#的默认编码器与某些字符的工作方式不同。
C#:
Console.Write(Encoding.Default.GetBytes(new char[] { (char)149 })[0]);
VB:
Dim b As Char() = {Chr(149)}
Console.WriteLine(Encoding.Default.GetBytes(b)(0))
C#输出为63,而VB是149的正确字节值。 如果您使用任何其他值,如145等,则输出匹配。
通过调试,VB和C#默认编码器都是SBCSCodePageEncoding。
有谁知道这是为什么?
我已经通过直接初始化一个字节数组来纠正了示例代码,它本来应该是第一个,但是我仍然想知道为什么不应该是语言特定的编码器看起来就是那个。 / p>
答案 0 :(得分:10)
如果您使用ChrW(149),您将获得不同的结果 - 63,与C#相同。
Dim b As Char() = {ChrW(149)}
Console.WriteLine(Encoding.Default.GetBytes(b)(0))
阅读the documentation以查看差异 - 这将解释答案
答案 1 :(得分:5)
VB Chr函数接受0到255范围内的参数,并使用当前默认代码页将其转换为字符。如果你传递一个超出这个范围的参数,它将抛出异常。
ChrW将采用16位值并返回相应的System.Char值而不使用编码 - 因此将得到与您发布的C#代码相同的结果。
在不使用VB Strings类(包含Chr和ChrW的类)的情况下,C#中VB代码的近似值将是:
char[] chars = Encoding.Default.GetChars(new byte[] { 149 });
Console.Write(Encoding.Default.GetBytes(chars)[0]);
答案 2 :(得分:0)
default encoding取决于机器以及线程,因为它使用当前代码页。您通常应该使用类似Encoding.UTF8的东西,这样您就不必担心当一台机器使用unicode而另一台机器使用1252-ANSI时会发生什么。
答案 3 :(得分:0)
不同的操作系统可能会使用 不同的编码作为默认值。 因此,数据从一个流传输 操作系统可能是另一个 翻译不正确。为了确保 编码的字节被解码 正确地,您的应用程序应该使用 Unicode编码,即 UTF8编码,UnicodeEncoding或 UTF32Encoding,带前导码。 另一个选择是使用a 更高级别的协议,以确保 相同的格式用于编码 和解码。
来自http://msdn.microsoft.com/en-us/library/system.text.encoding.default.aspx
使用utf8进行显式编码时,可以检查每种语言产生的内容吗?
答案 4 :(得分:0)
我相信VB中的等价物是ChrW(149)。
所以,这个VB代码......
Dim c As Char() = New Char() { Chr(149) }
'Dim c As Char() = New Char() { ChrW(149) }
Dim b As Byte() = System.Text.Encoding.Default.GetBytes(c)
Console.WriteLine("{0}", Convert.ToInt32(c(0)))
Console.WriteLine("{0}", CInt(b(0)))
生成与此C#代码相同的输出...
var c = new char[] { (char)149 };
var b = System.Text.Encoding.Default.GetBytes(c);
Console.WriteLine("{0}", (int)c[0]);
Console.WriteLine("{0}", (int) b[0]);