Java 从不带破折号的字符串创建UUID
如何从没有破折号的字符串创建java.util.UUIDJava 从不带破折号的字符串创建UUID,java,string,clojure,uuid,Java,String,Clojure,Uuid,如何从没有破折号的字符串创建java.util.UUID "5231b533ba17478798a3f2df37de2aD7" => #uuid "5231b533-ba17-4787-98a3-f2df37de2aD7" 你可以做一个愚蠢的正则表达式替换: String digits=“5231b53ba17478798a3f2df37de2ad7”; 字符串uuid=数字。replaceAll( “(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})”,
"5231b533ba17478798a3f2df37de2aD7" => #uuid "5231b533-ba17-4787-98a3-f2df37de2aD7"
你可以做一个愚蠢的正则表达式替换:
String digits=“5231b53ba17478798a3f2df37de2ad7”;
字符串uuid=数字。replaceAll(
“(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})”,
"$1-$2-$3-$4-$5");
System.out.println(uuid);//=>5231b533-ba17-4787-98a3-f2df37de2aD7
Clojure的#uuid
是一个传递到。并且,fromString
将其按“-”分隔,并将其转换为两个Long
值。(的格式标准化为8-4-4-4-12十六进制数字,但“-”实际上仅用于验证和视觉识别。)
直接的解决方案是重新插入“-”并使用
如果想要不带正则表达式的内容,可以使用and
tl;博士
5231b533-ba17-4787-98a3-f2df37de2ad7
或者将字符串的每一半解析为long
整数,并传递给
位,而不是文本
A是一个128位的值。UUID实际上不是由字母和数字组成的,它是由位组成的。你可以认为它描述了一个非常非常大的数字
我们可以将这些位显示为128个0
和1
字符
0111 0100 1101 0010 0101 0001 0101 0110
0110 0000 1110 0110 0100 0100 0100 1100
1010 0001 0111 0111 1010 1001 0110 1110
01100111101111011111111000101111
人类不容易读取位,因此为了方便起见,我们通常将128位值表示为由字母和数字组成的字符串
74d25156-60e6-444c-a177-a96e67ecfc5f
这样的十六进制字符串不是UUID本身,只是一种人性化的表示。连字符是按照UUID规范作为规范格式添加的,但是是可选的
74D2515660E64444CA177A96E67ECFC5F
顺便说一下,UUID规范明确规定,在生成十六进制字符串时必须使用小写字母,而应允许将大写作为输入。不幸的是,许多实现违反了小写生成规则,包括苹果、微软和其他公司的实现。看
下面提到的是Java,而不是Clojure 在Java7(及更早版本)中,您可以使用该类基于十六进制字符串(以连字符作为输入)实例化UUID。例如:
java.util.UUID uuidFromHyphens = java.util.UUID.fromString("6f34f25e-0b0d-4426-8ece-a8b3f27f4b63");
System.out.println( "UUID from string with hyphens: " + uuidFromHyphens );
但是,UUID类输入不带连字符的十六进制字符串失败。这种失败是不幸的,因为UUID规范不需要十六进制字符串表示形式中的连字符。这失败了:
java.util.UUID uuidFromNoHyphens = java.util.UUID.fromString("6f34f25e0b0d44268ecea8b3f27f4b63");
正则表达式
一种解决方法是格式化十六进制字符串以添加规范连字符。下面是我尝试使用正则表达式格式化十六进制字符串的过程。小心…这段代码行得通,但我不是正则表达式专家。您应该使这段代码更加健壮,比如检查字符串的长度在格式化之前是32个字符,在格式化之后是36个字符
// -----| With Hyphens |----------------------
java.util.UUID uuidFromHyphens = java.util.UUID.fromString( "6f34f25e-0b0d-4426-8ece-a8b3f27f4b63" );
System.out.println( "UUID from string with hyphens: " + uuidFromHyphens );
System.out.println();
// -----| Without Hyphens |----------------------
String hexStringWithoutHyphens = "6f34f25e0b0d44268ecea8b3f27f4b63";
// Use regex to format the hex string by inserting hyphens in the canonical format: 8-4-4-4-12
String hexStringWithInsertedHyphens = hexStringWithoutHyphens.replaceFirst( "([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5" );
System.out.println( "hexStringWithInsertedHyphens: " + hexStringWithInsertedHyphens );
java.util.UUID myUuid = java.util.UUID.fromString( hexStringWithInsertedHyphens );
System.out.println( "myUuid: " + myUuid );
Posix符号
在正则表达式中使用Posix表示法,\\p{XDigit}
取代了[0-9a-fA-F]
,您可能会发现这种替代语法更具可读性(请参见文档):
完整的例子
java.util.UUID uuid =
java.util.UUID.fromString (
"5231b533ba17478798a3f2df37de2aD7"
.replaceFirst (
"(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)",
"$1-$2-$3-$4-$5"
)
);
System.out.println ( "uuid.toString(): " + uuid );
uuid.toString():5231b533-ba17-4787-98a3-f2df37de2ad7
Regexp解决方案可能更快,但您也可以看看:) 顺便说一下,从16个二进制字节到uuid的转换
InputStream is = ..binarty input..;
byte[] bytes = IOUtils.toByteArray(is);
ByteBuffer bb = ByteBuffer.wrap(bytes);
UUID uuidWithDashesObj = new UUID(bb.getLong(), bb.getLong());
String uuidWithDashes = uuidWithDashesObj.toString();
也许其他人可以评论这种方法的计算效率。(这与我的应用程序无关。)与使用regexp和字符串操作相比,一个快得多(~900%)的解决方案是只将十六进制字符串解析为两个长字符串,并从以下内容创建UUID实例:
(defn uuid-from-string
"Converts a 32digit hex string into java.util.UUID"
[hex]
(java.util.UUID.
(Long/parseUnsignedLong (subs hex 0 16) 16)
(Long/parseUnsignedLong (subs hex 16) 16)))
另一个解决方案类似于Pawel的解决方案,但不创建新字符串,只解决问题。如果性能是一个问题,避免像瘟疫一样使用regex/split/replaceAll和UUID.fromString
String hyphenlessUuid = in.nextString();
BigInteger bigInteger = new BigInteger(hyphenlessUuid, 16);
new UUID(bigInteger.shiftRight(64).longValue(), bigInteger.longValue());
我相信以下是最快的表现。它甚至比它的速度稍快。它是源代码中经过轻微修改的代码
公共静态UUID from32(
字符串id){
if(id==null){
抛出新的NullPointerException();
}
如果(id.length()!=32){
抛出新的NumberFormatException(“UUID必须是32个字符,没有连字符”);
}
龙洛,你好,;
lo=hi=0;
对于(int i=0,j=0;i<32;++j){
国际货币;
char c=id.charAt(i);
如果(c>='0'&&c='a'&&c='a'&&c的答案的优化版本:
String[] digitsList= {
"daa70a7ffa904841bf9a81a67bdfdb45",
"529737c950e6428f80c0bac104668b54",
"5673c26e2e8f4c129906c74ec634b807",
"dd5a5ee3a3c44e4fb53d2e947eceeda5",
"faacc25d264d4e9498ade7a994dc612e",
"9a1d322dc70349c996dc1d5b76b44a0a",
"5fcfa683af5148a99c1bd900f57ea69c",
"fd9eae8272394dfd8fd42d2bc2933579",
"4b14d571dd4a4c9690796da318fc0c3a",
"d0c88286f24147f4a5d38e6198ee2d18"
};
//Use compiled pattern to improve performance of bulk operations
Pattern pattern = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})");
for (int i = 0; i < digitsList.length; i++)
{
String uuid = pattern.matcher(digitsList[i]).replaceAll("$1-$2-$3-$4-$5");
System.out.println(uuid);
}
String[]数字列表={
“daa70a7ffa904841bf9a81a67bdfdb45”,
“529737c950e6428f80c0bac104668b54”,
“5673c26e2e8f4c129906c74ec634b807”,
“DD5A5EE3A344E4FB53D2E947ECEEAD5”,
“faacc25d264d4e9498ade7a994dc612e”,
“9a1d322dc70349c996dc1d5b76b44a0a”,
“5fcfa683af5148a99c1bd900f57ea69c”,
“FD9EAE8272394DF8FD42D2BC2933579”,
“4b14d571dd4a4c9690796da318fc0c3a”,
“d0c88286f24147f4a5d38e6198ee2d18”
};
//使用编译模式提高批量操作的性能
Pattern Pattern=Pattern.compile(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})”;
for(int i=0;i
以下是一个更快的示例,因为它不使用regexp
公共类示例1{
/**
*从32个字符的十六进制中获取UUID。
*
*@param string一个十六进制字符串
*@返回UUID
*/
公共静态UUID TOUID(字符串){
if(string==null | | string.length()!=32){
抛出新的IllegalArgumentException(“无效输入字符串!”);
}
char[]input=string.toCharArray();
字符[]输出=新字符[36];
java.util.UUID uuid =
java.util.UUID.fromString (
"5231b533ba17478798a3f2df37de2aD7"
.replaceFirst (
"(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)",
"$1-$2-$3-$4-$5"
)
);
System.out.println ( "uuid.toString(): " + uuid );
String withoutDashes = "44e128a5-ac7a-4c9a-be4c-224b6bf81b20".replaceAll("-", "");
BigInteger bi1 = new BigInteger(withoutDashes.substring(0, 16), 16);
BigInteger bi2 = new BigInteger(withoutDashes.substring(16, 32), 16);
UUID uuid = new UUID(bi1.longValue(), bi2.longValue());
String withDashes = uuid.toString();
InputStream is = ..binarty input..;
byte[] bytes = IOUtils.toByteArray(is);
ByteBuffer bb = ByteBuffer.wrap(bytes);
UUID uuidWithDashesObj = new UUID(bb.getLong(), bb.getLong());
String uuidWithDashes = uuidWithDashesObj.toString();
public static String addUUIDDashes(String idNoDashes) {
StringBuffer idBuff = new StringBuffer(idNoDashes);
idBuff.insert(20, '-');
idBuff.insert(16, '-');
idBuff.insert(12, '-');
idBuff.insert(8, '-');
return idBuff.toString();
}
(defn uuid-from-string
"Converts a 32digit hex string into java.util.UUID"
[hex]
(java.util.UUID.
(Long/parseUnsignedLong (subs hex 0 16) 16)
(Long/parseUnsignedLong (subs hex 16) 16)))
String hyphenlessUuid = in.nextString();
BigInteger bigInteger = new BigInteger(hyphenlessUuid, 16);
new UUID(bigInteger.shiftRight(64).longValue(), bigInteger.longValue());
public static UUID from32(
String id) {
if (id == null) {
throw new NullPointerException();
}
if (id.length() != 32) {
throw new NumberFormatException("UUID has to be 32 char with no hyphens");
}
long lo, hi;
lo = hi = 0;
for (int i = 0, j = 0; i < 32; ++j) {
int curr;
char c = id.charAt(i);
if (c >= '0' && c <= '9') {
curr = (c - '0');
}
else if (c >= 'a' && c <= 'f') {
curr = (c - 'a' + 10);
}
else if (c >= 'A' && c <= 'F') {
curr = (c - 'A' + 10);
}
else {
throw new NumberFormatException(
"Non-hex character at #" + i + ": '" + c + "' (value 0x" + Integer.toHexString(c) + ")");
}
curr = (curr << 4);
c = id.charAt(++i);
if (c >= '0' && c <= '9') {
curr |= (c - '0');
}
else if (c >= 'a' && c <= 'f') {
curr |= (c - 'a' + 10);
}
else if (c >= 'A' && c <= 'F') {
curr |= (c - 'A' + 10);
}
else {
throw new NumberFormatException(
"Non-hex character at #" + i + ": '" + c + "' (value 0x" + Integer.toHexString(c) + ")");
}
if (j < 8) {
hi = (hi << 8) | curr;
}
else {
lo = (lo << 8) | curr;
}
++i;
}
return new UUID(hi, lo);
}
String[] digitsList= {
"daa70a7ffa904841bf9a81a67bdfdb45",
"529737c950e6428f80c0bac104668b54",
"5673c26e2e8f4c129906c74ec634b807",
"dd5a5ee3a3c44e4fb53d2e947eceeda5",
"faacc25d264d4e9498ade7a994dc612e",
"9a1d322dc70349c996dc1d5b76b44a0a",
"5fcfa683af5148a99c1bd900f57ea69c",
"fd9eae8272394dfd8fd42d2bc2933579",
"4b14d571dd4a4c9690796da318fc0c3a",
"d0c88286f24147f4a5d38e6198ee2d18"
};
//Use compiled pattern to improve performance of bulk operations
Pattern pattern = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})");
for (int i = 0; i < digitsList.length; i++)
{
String uuid = pattern.matcher(digitsList[i]).replaceAll("$1-$2-$3-$4-$5");
System.out.println(uuid);
}