Java和C#中的UTF-16编码差异

11

我正在尝试读取一个以UTF-16编码方案编码的字符串,并对其执行MD5哈希。但奇怪的是,当我尝试这样做时,Java和C#返回了不同的结果。

以下是Java代码片段:

public static void main(String[] args) {
    String str = "preparar mantecado con coca cola";
    try {
        MessageDigest digest = MessageDigest.getInstance("MD5");
        digest.update(str.getBytes("UTF-16"));
        byte[] hash = digest.digest();
        String output = "";
        for(byte b: hash){
            output += Integer.toString( ( b & 0xff ) + 0x100, 16).substring( 1 );
        }
        System.out.println(output);
    } catch (Exception e) {

    }
}

这段代码的输出为:249ece65145dca34ed310445758e5504

下面是C#代码示例:

   public static string GetMD5Hash()
        {
            string input = "preparar mantecado con coca cola";
            System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] bs = System.Text.Encoding.Unicode.GetBytes(input);
            bs = x.ComputeHash(bs);
            System.Text.StringBuilder s = new System.Text.StringBuilder();
            foreach (byte b in bs)
            {
                s.Append(b.ToString("x2").ToLower());
            }
            string output= s.ToString();
            Console.WriteLine(output);
        }

输出结果为:c04d0f518ba2555977fa1ed7f93ae2b3

我不确定为什么输出结果不同。我们如何修改上面的代码,以便两个输出结果相同?


首先比较您的字节数组。即使只有一个位不匹配,哈希值也完全不同。在UTF-16编码中可能会有BOM或其他内容。它可能是小端或大端,或者其他任何形式。 - maaartinus
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
35

UTF-16 != UTF-16.

在Java中,getBytes("UTF-16")返回一个带有可选的字节顺序标记的大端表示形式。C#的System.Text.Encoding.Unicode.GetBytes则返回一个小端表示形式。我无法从这里检查您的代码,但我认为您需要精确指定转换方式。

在Java版本中尝试使用getBytes("UTF-16LE")


值得注意的是,如果您在Eclipse中查看输出,它仍然与Visual Studio显示的不匹配。但奇怪的是,它确实起作用... - debracey
2015年,基于波兰语的Java 8.0 * .NET 4.0.x测试看起来像你所写的那样没问题。两种语言中的字节是相同的,并且都没有BOM前缀。下一个重要的测试领域是:Java算术在溢出时会默默地接受(对哈希很好),而C#默认情况下不会。 - Jacek Cz

5

我发现的第一个问题(这可能不是唯一的问题)是C#的Encoding.Unicode.GetBytes()方法是小端字节序,而Java的自然字节序是大端字节序。


0
你可以使用 System.Text.Enconding.Unicode.GetString(byte[]) 将字节转换回字符串。这样,你就可以确保所有内容都是以 Unicode 编码进行的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,