有没有什么办法可以在Java中生成一个与在C#中生成的UUID相同的UUID?(Is there any way to generate a UUID in Java that is identica

编程入门 行业动态 更新时间:2024-10-25 00:28:51
有没有什么办法可以在Java中生成一个与在C#中生成的UUID相同的UUID?(Is there any way to generate a UUID in Java that is identical to that of the one generated in C#?) java

我将一个C#脚本移植到Spark(Scala)中,我遇到了Scala中的UUID生成问题,以及C#中GUID生成的问题。

有没有什么办法可以在Java中生成一个与在C#中生成的UUID相同的UUID?

我通过从字符串的MD5散列创建Guid来为数据库生成主键。 最终,我想在Java / Scala中生成与C#脚本相匹配的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 Guid: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#中前三个字段的字节顺序。 第四和第五个字节不同(红色) 为了表示UUID的版本和变体,Java切换6-7位,这可能解释字节4和5的差异。 这似乎是路障。 我知道Java使用带符号的字节,而C#具有无符号的字节; 这也可能是相关的。

缺少操纵字节,有没有其他方法可以解决这个问题?

I'm porting a C# script into Spark (Scala) and I'm running into an issue with UUID generation in Scala vs GUID generation in C#.

Is there any way to generate a UUID in Java that is identical to that of the one generated in C#?

I'm generating the primary key for a database by creating a Guid from the MD5 hash of a string. Ultimately, I'd like to generate UUIDs in Java/Scala that match those from the C# script, so the existing data in the database that used the C# implementation for hashing doesn't need to be rehashed.

C# to port:

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 ported code:

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)

Result from C#

String to hash: 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

Result from Scala

String to hash: Hello World MD5: b10a8db164e0754105b7a99be72e3fe5 UUID: b10a8db1-64e0-3541-85b7-a99be72e3fe5

What works:

MD5 Hashes (which the GUID and UUID are based off of) match

What doesn't:

First three fields have endianness switched in C# (orange) C#'s GUID chooses native byte ordering for the first three fields (4, 2, 2), which in this case is little endian and Big Endian for the last field (8), while Java's UUID uses Big Endian ordering for all four fields; this explains the byte ordering in the first three fields in C#. Fourth and fifth bytes are different (red) Java switches 6-7 bits in order to denote version and variant of UUID, this might explain the differences in bytes 4 and 5. This seems to be the roadblock. I understand that Java uses signed bytes, while C# has unsigned bytes; this might be relevant as well.

Short of manipulating bytes, is there any other way to fix this?

最满意答案

TL; DR

如果你希望你的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 。 唉, ToString和ToByteArray不会以相同的顺序返回字节。

TL;DR

If you want your C# and your Java to act exactly the same way (and you are happy with the existing C# behaviour), you'll need to manually re-order some of the bytes in uuid_bytes (i.e. swap some of the entries you identified as out of order).

Additionally, you should not use:

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

But instead use:

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

Shamelessly stolen from https://stackoverflow.com/a/24409153/34092 :)

Additional Background

In case you weren't aware, when dealing with C#'s 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.

In your C#, rather than using:

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

you may want to consider using:

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

Your existing code calls ToString behind the scenes. Alas, ToString and ToByteArray do not return the bytes in the same order.

更多推荐

本文发布于:2023-08-05 03:42:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1427993.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:有没有什么   办法   Java   UUID   identical

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!