我将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#的结果
Scala的结果
什么有效:
什么不是:
没有操纵字节,还有其他方法可以解决这个问题吗?
答案 0 :(得分:5)
如果您希望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时:
请注意,返回的字节数组中的字节顺序是不同的 来自Guid值的字符串表示。的顺序 开始的四字节组和接下来的两个双字节组是 反转,而最后两个字节组的顺序和结束 六字节组是一样的。该示例提供了一个说明。
And:
ToString方法返回的十六进制字符串的顺序 取决于计算机体系结构是否为little-endian或 大端。
在您的C#中,而不是使用:
Console.WriteLine("Guid: {0}", guid);
您可能需要考虑使用:
Console.WriteLine(BitConverter.ToString(guid.ToByteArray()));
您现有的代码在幕后调用ToString
。唉,ToString
和ToByteArray
不会返回same order中的字节。