Java 从不带破折号的字符串创建UUID

Java 从不带破折号的字符串创建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})”,

如何从没有破折号的字符串创建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})”,
"$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);
    }