当前位置: 首页 > 知识库问答 >
问题:

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

贡和裕
2023-03-14

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

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

我通过从字符串的MD5散列创建Guid来生成数据库的主键。最后,我希望在Java/Scala中生成与C#脚本中的UUIDs相匹配的UUIDs,这样数据库中使用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
  • Guid:b18d0ab1-e064-4175-05b7-a99be72e3fe5

Scala的结果

    < li >要哈希的字符串:Hello World < Li > MD5:b 10 A8 db 164 e 0754105 b 7 a 99 be 72 E3 Fe 5 < Li > UUID:b 10 A8 db 1-64e 0-3541-85b 7-a 99 be 72 E3 Fe 5

有效方法:

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

什么不:

    < li >在C#中,前三个字段的字符顺序已经切换(橙色) < ul > < li>C#的GUID为前三个字段(4,2,2)选择本机字节排序,在本例中为最后一个字段(8)选择小端和大端,而Java的UUID对所有四个字段使用大端排序;这解释了C#中前三个字段的字节顺序。
  • Java 切换 6-7 位以表示 UUID 的版本和变体,这可能解释了字节 4 和 5 的差异。这似乎是障碍。

除了操作字节,还有其他方法可以解决这个问题吗?

共有1个答案

陆弘新
2023-03-14

如果您希望您的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#的GUID时:

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

并且:

ToString方法返回的十六进制字符串的顺序取决于计算机体系结构是小端还是大端。

在 C# 中,而不是使用:

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

您可能需要考虑使用:

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

您的现有代码在幕后调用ToString。唉,ToStringToByteArray不按相同的顺序返回字节。

 类似资料:
  • 我想知道是否有一种方法可以基于字符串生成相同的UUID 我尝试使用UUID,它似乎没有提供此功能。

  • 问题内容: 我想知道是否有一种方法可以根据 我尝试过的UUID 生成相同的UUID,但它似乎不提供此功能。 问题答案: 您可以通过这种方式使用UUID来为您的输入String始终获取相同的UUID:

  • 问题内容: 我有看起来像这样的代码: 它返回一个长度为32的字符串,但我认为它不是有效的UUID。如果它是一个真正的UUID,为什么它是一个UUID,什么是代码,修改的值的目的和。 有没有更好的方法来生成UUID? 问题答案: 这些行将字节6和8的值限制在特定范围内。返回range内的随机字节,这些字节不是UUID的所有有效值。据我所知,这应该对片中的所有值进行。 如果您使用的是Linux,则可以

  • 假设我生成了一个具有多个属性的域对象。我想为defn类中的一个对象属性生成@jsonignore注释。

  • 我的印象是,UUID规范需要一个有保证的、真实的、全球唯一的结果,不是99.999999999999%的唯一结果,而是100%的唯一结果。从规格来看: UUID为128位长,可以保证跨空间和时间的唯一性。 看起来java只支持UUID规范的V3和V4。V4并不是真正独特的。对于使用< code > namuuidfrombytes 的V3实现,下面的结果是重复的,因为计算机太快了(编辑:循环到10

  • 问题内容: 下面的代码旨在生成间隔为[1,100]的五个伪随机数的列表。我为with设置了种子,它以unix时间返回系统时间。当我使用Microsoft Visual Studio 2013在Windows 7上编译并运行该程序时,它会按预期运行(请参阅下文)。但是,当我在Arch Linux中使用g ++编译器执行此操作时,它的行为就很奇怪。 在Linux中,每次将生成5个数字。每次执行后4个数