Sun/Oracle JDK公开了一个函数,用于在java.util包中创建类型3(基于名称) UUID : java.util.UUID.nameUUIDFromBytes(byte[] name)。
我需要能够使用nameUUIDFromBytes在Java语言中生成Type3UUID,并在用另一种语言创建Type3UUID时得到相同的UUID,假设我提供了与源文件相同的字节。
根据javadoc,此函数创建符合RFC4122的Type3UUID。但是,根据RFC 4122规范,类型3UUID必须在某个名称空间中创建。大多数其他语言允许您在创建Type3UUID时指定名称空间(例如Ruby中的UUIDTools gem )。
所以我的问题是:当我调用nameUUIDFromBytes时,JDK使用了什么名称空间UUID?
发布于 2012-03-01 03:02:35
请参阅this bug report
尤其是底部的评论:
也许在这一点上的行动过程应该是修复说明“nameUUIDFromBytes( IETF )”的javadoc“一个人应该传入一个字节数组,其中包含名称空间UUID的字节和名称字节的连接(按该顺序)”,这假设该方法只是md5的byte[]的namespaceAndName,并根据IETF文档设置字段。
我不知道我是否相信它能正确工作,但与其他实现生成的相同UUID相比,使用UUID规范中的预定义名称规范进行测试应该很容易。
发布于 2012-10-30 20:20:41
示例代码:
String NameSpace_OID_string = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
UUID NameSpace_OID_uuid = UUID.fromString(NameSpace_OID_string);
long msb = NameSpace_OID_uuid.getMostSignificantBits();
long lsb = NameSpace_OID_uuid.getLeastSignificantBits();
byte[] NameSpace_OID_buffer = new byte[16];
for (int i = 0; i < 8; i++) {
NameSpace_OID_buffer[i] = (byte) (msb >>> 8 * (7 - i));
}
for (int i = 8; i < 16; i++) {
NameSpace_OID_buffer[i] = (byte) (lsb >>> 8 * (7 - i));
}
String name = "user123";
byte[] name_buffer = name.getBytes();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
try {
outputStream.write( NameSpace_OID_buffer);
outputStream.write( name_buffer );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte byteArray[] = outputStream.toByteArray();
System.out.println(UUID.nameUUIDFromBytes(byteArray).toString());发布于 2021-09-14 04:31:54
UUID.nameUUIDFromBytes()方法不使用名称空间来生成UUID v3。它只是使用MD5散列“名称”。
必须手动将命名空间字节(16字节)与“name”字节连接起来。下面的两个示例在调用UUID.nameUUIDFromBytes()之前使用ByteBuffer和System.arraycopy()连接'namespace‘和'name’。
使用'ByteBuffer‘的示例
package com.example;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class Example1 {
/**
* Returns a name-based UUID v3 using a namespace.
*
* @param namespace a UUID
* @param name a string
* @return a UUID
*/
public static UUID getNameBased(UUID namespace, String name) {
// 1. Get the NAMESPACE bytes
final byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
// 2. Concatenate NAMESPACE and NAME bytes
ByteBuffer buffer = ByteBuffer.allocate(nameBytes.length + 16);
buffer.putLong(namespace.getMostSignificantBits());
buffer.putLong(namespace.getLeastSignificantBits());
buffer.put(nameBytes);
// 3. Generate a name-based UUID
return UUID.nameUUIDFromBytes(buffer.array());
}
public static void main(String[] args) {
UUID namespace = UUID.fromString("11111111-2222-3333-4444-555555555555");
String name = "this is a test";
UUID uuid = getNameBased(namespace, name);
System.out.println(uuid); // prints: 04334e59-716d-3078-9722-63e2ec20d4ec
}
}使用'System.arraycopy()‘的示例
package com.example;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class Example2 {
/**
* Returns a name-based UUID v3 using a namespace.
*
* @param namespace a UUID
* @param name a string
* @return a UUID
*/
public static UUID getNameBased(UUID namespace, String name) {
// 1. Get NAMESPACE and NAME bytes
final byte[] msb = toBytes(namespace.getMostSignificantBits());
final byte[] lsb = toBytes(namespace.getLeastSignificantBits());
final byte[] nam = name.getBytes(StandardCharsets.UTF_8);
// 2. Concatenate NAMESPACE and NAME bytes
final byte[] bytes = new byte[16 + nam.length];
System.arraycopy(msb, 0, bytes, 0, 8);
System.arraycopy(lsb, 0, bytes, 8, 8);
System.arraycopy(nam, 0, bytes, 16, nam.length);
// 3. Generate a name-based UUID
return UUID.nameUUIDFromBytes(bytes);
}
private static byte[] toBytes(final long number) {
return new byte[] { (byte) (number >>> 56), (byte) (number >>> 48), (byte) (number >>> 40),
(byte) (number >>> 32), (byte) (number >>> 24), (byte) (number >>> 16), (byte) (number >>> 8),
(byte) (number) };
}
public static void main(String[] args) {
UUID namespace = UUID.fromString("11111111-2222-3333-4444-555555555555");
String name = "this is a test";
UUID uuid = getNameBased(namespace, name);
System.out.println(uuid); // prints: 04334e59-716d-3078-9722-63e2ec20d4ec
}
}库
有两个库可以使用名称空间生成v3和v5:
https://stackoverflow.com/questions/9504519
复制相似问题