您可以将UUID转换为字符串,实际上是以下16位char
8个元素的序列。
static String encodeUuid(final UUID id) {
final long hi = id.getMostSignificantBits()
final long lo = id.getLeastSignificantBits()
return new String(new char[] {
(char) ((hi >>> 48) & 0xffff), (char) ((hi >>> 32) & 0xffff),
(char) ((hi >>> 16) & 0xffff), (char) ((hi ) & 0xffff),
(char) ((lo >>> 48) & 0xffff), (char) ((lo >>> 32) & 0xffff),
(char) ((lo >>> 16) & 0xffff), (char) ((lo ) & 0xffff)
})
}
static UUID decodeUuid(final String enc) {
final char[] cs = enc.toCharArray()
return new UUID(
(long) cs[0] << 48 | (long) cs[1] << 32 | (long) cs[2] << 16 | (long) cs[3],
(long) cs[4] << 48 | (long) cs[5] << 32 | (long) cs[6] << 16 | (long) cs[7]
)
}
这段代码看起来确实应该可以工作(你可以在这里尝试一下),并且大多数情况下可以使用UTF-8和UTF-16进行编码/解码而没有问题:
static boolean validate(final UUID id, final Charset cs) {
final ByteBuffer buf = cs.encode(encodeUuid(id));
final UUID _id = decodeUuid(cs.decode(buf).toString());
return id.equals(_id);
}
public static void main(final String[] argv) {
final UUID id = UUID.randomUUID();
assert validate(id, StandardCharsets.UTF_8) : "failed using utf-8";
assert validate(id, StandardCharsets.UTF_16) : "failed using utf-16";
}
C:\dev\scrap>javac UuidTest.java
C:\dev\scrap>java -ea UuidTest
然而,确实存在一些UTF-16代码点被保留为代理项的问题。如果发生这种情况,编码将无法正常工作,您将无法重构原始UUID。有关更多信息,请参阅上面机械蜗牛的回复。
从通过 UUID.randomUUID 生成的编码 UUID 中,您可以一致地实际 删除 的唯一数据是用于 variant
(始终为 2
)和用于 version
的 4 位(始终为 4
)。
存在不同变体的全局标识符。该类的方法用于操作Leach-Salz变体,但构造函数允许创建任何UUID的变体(如下所述)。
变体2(Leach-Salz)UUID的布局如下:最高有效位长包含以下无符号字段:
0xFFFFFFFF00000000 time_low
0x00000000FFFF0000 time_mid
0x000000000000F000 version
0x0000000000000FFF time_hi
最低有效位长包含以下无符号字段:
0xC000000000000000 variant
0x3FFF000000000000 clock_seq
0x0000FFFFFFFFFFFF node
变体字段包含一个值,用于标识UUID的布局。上述位布局仅适用于具有变体值2的UUID,该值指示Leach-Salz变体。
版本字段保存描述此UUID类型的值。 UUID有四种不同的基本类型:基于时间、DCE安全性、基于名称和随机生成的UUID。这些类型的版本值分别为1、2、3和4。