java - 有什么方法可以在 Java 中生成与在 C# 中生成的 UUID 相同的 UUID?

标签 java c# scala hash 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));
} 

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)

C# 的结果

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

Scala 的结果

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

什么有效:

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

什么不是:

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

缺少对字节的操作,还有其他方法可以解决这个问题吗?

最佳答案

长话短说

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

此外,您不应使用:

UUID.nameUUIDFromBytes(to_encode.trim().getBytes())

而是使用:

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();
}

无耻地从 https://stackoverflow.com/a/24409153/34092 偷来的:)

其他背景

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

Note that the order of bytes in the returned byte array is different from the string representation of a Guid value. The order of the beginning four-byte group and the next two two-byte groups is reversed, whereas the order of the last two-byte group and the closing six-byte group is the same. The example provides an illustration.

And :

The order of hexadecimal strings returned by the ToString method depends on whether the computer architecture is little-endian or big-endian.

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

Console.WriteLine("Guid: {0}", guid);

您可能要考虑使用:

Console.WriteLine(BitConverter.ToString(guid.ToByteArray()));

您现有的代码在幕后调用 ToString。唉,ToStringToByteArray 不返回 same order 中的字节.

关于java - 有什么方法可以在 Java 中生成与在 C# 中生成的 UUID 相同的 UUID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45337638/

相关文章:

java - 使用 HttpURLConnection 提交 json POST 请求

scala - 如何从 Scala 中的 Some() 中提取值

java - Linux 的 getDesktopProperty() 是什么?

java - Maven:复制到 FTP 抛出 java.io.IOException:非法搜索

java - 在按钮单击上添加 JLabel 但不显示

c# - 在 Uri TryCreate 完美运行时使用 Uri IsWellFormedUriString

c# - 如何使用正则表达式拆分字符串以返回值列表?

scala - Spark SQL 未正确转换时区

java - 在 SWT 中禁用窗口调整大小 - 使用复合

c# - 绑定(bind)和标记扩展设计器构造函数错误