C# Java与C中的UTF-16编码#

C# Java与C中的UTF-16编码#,c#,java,encoding,md5,utf-16,C#,Java,Encoding,Md5,Utf 16,我正在尝试读取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");

我正在尝试读取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) {

    }
}
   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);
        }
其输出为:249ECE65145DCA34ED31044585E504

以下是C#中的一段代码:

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) {

    }
}
   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!=UTF-16

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


在Java版本中尝试
getBytes(“UTF-16LE”)

我能找到的第一件事,这可能不是唯一的问题,就是C#的Encoding.Unicode.getBytes()是littleendian,而Java的自然字节顺序是bigendian。

可以使用
System.Text.Enconding.Unicode.GetString(byte[])
将字节转换回字符串。通过这种方式,您可以确保所有操作都以Unicode编码方式进行。

首先比较字节数组。如果它们在哪怕是一个位上都不匹配,那么散列就完全不同了。UTF-16编码中可能有BOM或任何内容。它可能是小端或大端,或者其他什么。值得注意的是,如果您在eclipse中查看输出,它仍然与VisualStudio显示的内容不匹配。但奇怪的是,它确实起作用了……2015年,基于波兰语的Java 8.0*.NET 4.0.x测试,看起来和你写的一样。两种语言中的字节相同,并且没有BOM表前缀。测试的下一个重要字段:Java算术以静默方式接受溢出(适用于散列),C#默认情况下不接受