有没有办法在Java中生成与C#中生成的UUID相同的UUID?

Ari*_*ein 8 c# java hash scala guid

我正在将一个C#脚本移植到Spark(Scala)中,我遇到了Scala中UUID生成与C#中GUID生成的问题.

有没有办法在Java中生成与C#中生成的UUID相同的UUID?

我通过从字符串的MD5哈希创建Guid来为数据库生成主键.最后,我想在Java/Scala中生成与C#脚本中的UUID匹配的UUID,因此使用C#实现进行散列的数据库中的现有数据不需要重新散列.

C#到端口:

String ex = "Hello World";
Console.WriteLine("String to Hash: {0}", ex);
byte[] md5 = GetMD5Hash(ex);
Console.WriteLine("Hash: {0}", BitConverter.ToString(md5));
Guid guid = new Guid(md5);
Console.WriteLine("Guid: {0}", guid);

private static byte[] GetMD5Hash(params object[] values) {
  using (MD5 md5 = MD5.Create())
    return md5.ComputeHash(Encoding.UTF8.GetBytes(s));
} 
Run Code Online (Sandbox Code Playgroud)

Scala移植代码:

val to_encode = "Hello World"
val md5hash = MessageDigest.getInstance("MD5")
 .digest(to_encode.trim().getBytes())
val md5string = md5hash.map("%02x-".format(_)).mkString
val uuid_bytes = UUID.nameUUIDFromBytes(to_encode.trim().getBytes())
printf("String to encode: %s\n", to_encode)
printf("MD5: %s\n", md5string)
printf("UUID: %s\n", uuid_bytes.toString)
Run Code Online (Sandbox Code Playgroud)

来自C#的结果

  • 要散列的字符串:Hello World
  • MD5:B1-0A-8D-B1-64-E0-75-41-05-B7-A9-9B-E7-2E-3F-E5
  • 指导:b18d0ab1-e064-41 75 - 05 b7-a99be72e3fe5

Scala的结果

  • 要散列的字符串:Hello World
  • MD5:b10a8db164e0754105b7a99be72e3fe5
  • UUID:b10a8db1-64e0- 35 41- 85 b7-a99be72e3fe5

什么有效:

  • MD5哈希(GUID和UUID所基于的)匹配

什么不:

  • 前三个字段的字节序在C#中切换(橙色)
    • C#的GUID为前三个字段(4,2,2)选择本地字节排序,在这种情况下,最后一个字段是小端和Big Endian(8),而Java的UUID对所有四个字段使用Big Endian排序; 这解释了C#中前三个字段的字节顺序.
  • 第四和第五个字节不同(红色)
    • Java切换6-7位以表示UUID的版本和变体,这可以解释字节4和5的差异.这似乎是障碍.
  • 我知道Java使用有符号字节,而C#有无符号字节; 这也可能是相关的.

没有操纵字节,有没有其他方法来解决这个问题?

mjw*_*lls 5

TL; DR

如果您希望C#和Java以完全相同的方式运行(并且您对现有的C#行为感到满意),则需要手动重新排序一些字节uuid_bytes(即交换您标识为的一些条目)无序).

此外,您不应该使用:

UUID.nameUUIDFromBytes(to_encode.trim().getBytes())
Run Code Online (Sandbox Code Playgroud)

但改为使用:

public static String getGuidFromByteArray(byte[] bytes) {
    ByteBuffer bb = ByteBuffer.wrap(bytes);
    long high = bb.getLong();
    long low = bb.getLong();
    UUID uuid = new UUID(high, low);
    return uuid.toString();
}
Run Code Online (Sandbox Code Playgroud)

无耻地从/sf/answers/1708640741/ :) 被盗

附加背景

如果你不知道,在处理C#的GUID时:

请注意,返回的字节数组中的字节顺序与Guid值的字符串表示形式不同.开始的四字节组和接下来的两个双字节组的顺序相反,而最后两个字节组和结束六字节组的顺序相同.该示例提供了说明.

而且:

ToString方法返回的十六进制字符串的顺序取决于计算机体系结构是little-endian还是big-endian.

在你的C#中,而不是使用:

Console.WriteLine("Guid: {0}", guid);
Run Code Online (Sandbox Code Playgroud)

你可能想考虑使用:

Console.WriteLine(BitConverter.ToString(guid.ToByteArray()));
Run Code Online (Sandbox Code Playgroud)

您现有的代码ToString在幕后调用.唉,ToString并且ToByteArray不以相同的顺序返回字节.