传统算法以外的UUID编码方案(例如Base32、Base62)的替代方案

3
我们需要将大量的UUID转换为可与XML兼容的字符串。如果我们使用Base32算法(将每5位映射到32个字符之一),则会产生26个字符的字符串;如果我们使用Base62算法(迭代地将128位整数除以62,并将余数记录为62个字符之一),则会产生22个字符的字符串。虽然Base62返回更短的字符串,但它需要更多的CPU资源,因此我们只能使用Base32(由于XML,Base64不是一个选项)。
你知道还有其他类型的编码算法可以帮助我们吗?是否有类似于Base32的位模式编码算法的变体,可以与不是2的幂的基数一起使用?或者是否有混合算法将第一个算法和第二个算法的方法结合起来?如果可能的话,我们希望将字符字符串减少到不到26个字符。
2个回答

3
您提到了数字62,这意味着您将字母表限制为A-Z(大写和小写)和数字0-9。为什么不将另外几个XML兼容字符添加到该列表中,例如+.~!,以将该数字增加到64?这样,您就可以进行位移而不是除法,这应该使算法与Base32一样快,并减少字符串大小。
编辑:由于这些字符也适用于其他尚未指定的语言,因此您可能希望转义一些字符以表示您的64个选项。如果您使用_作为转义字符,您可以使用_1和_2表示选项63和64。原始问题中提到的统计数据表明UUIDS是128位,因此如果没有转义,则我们的Base64将给出22个字符,并且在最多转义4个项目的情况下,仍保持在您的26个字符内。

好的观点,谢谢!但 XML 不是我们唯一的限制,我们还需要在某些编程语言中使用它来生成类名(其中下划线将成为另一个字符,但我还没有找到第 64 个可用的 ASCII 字符)。 - Alexander233
@Carina - 我已经添加了一个建议,关于转义,如果你的字符用完了,这可能会有所帮助。如果可以的话,最好找到额外的第64个字符。 - borrible
1
您可能已经想到了,但也要意识到大多数编程语言不允许类名以数字开头。因此,您应该为所有这些加上一些合法字符的前缀。 - Ponkadoodle

0

维基百科提供了两个可在XML命名空间中使用的Base64版本。

http://en.wikipedia.org/wiki/Base64#XML。我编写了以下JAVA代码来进行URLSafe、Java中的UUID(调用theObjectReturned.toString()将其作为guid字符串返回)。

我看到其他Java代码,据说非常快速,并且可以轻松修改以执行XML安全变体:

http://iharder.sourceforge.net/current/java/base64/

代码如下。保存在名为 UUIDUtil.java 的文件中。

public class UUIDUtil{
public static UUID combUUID(){
    private UUID srcUUID = UUID.randomUUID();;
    private java.sql.Timestamp ts = new java.sql.Timestamp(Calendar.getInstance().getTime().getTime());

    long upper16OfLowerUUID = this.zeroLower48BitsOfLong( srcUUID.getLeastSignificantBits() );
    long lower48Time = UUIDUtil.zeroUpper16BitsOfLong( ts );
    long lowerLongForNewUUID = upper16OfLowerUUID | lower48Time;
    return new UUID( srcUUID.getMostSignificantBits(), lowerLongForNewUUID );
}   
public static base64URLSafeOfUUIDObject( UUID uuid ){
    byte[] bytes = ByteBuffer.allocate(16).putLong(0, uuid.getLeastSignificantBits()).putLong(8, uuid.getMostSignificantBits()).array();
    return Base64.encodeBase64URLSafeString( bytes );
}
public static base64URLSafeOfUUIDString( String uuidString ){
    UUID uuid = UUID.fromString( uuidString );
    return UUIDUtil.base64URLSafeOfUUIDObject( uuid );
}
private static long zeroLower48BitsOfLong( long longVar ){
    long upper16BitMask =  -281474976710656L;
    return longVar & upper16BitMask;
}
private static void zeroUpper16BitsOfLong( long longVar ){
    long lower48BitMask =  281474976710656L-1L;
    return longVar & lower48BitMask;
}

}


1
非常有趣。但是你在XML中提到的方法存在问题,因为元素名称不能以数字开头,也不能以'xml'或'XML'开头。无论是维基百科文章的方法还是base64URLSafeOfUUIDObject都会导致一些编码不符合这些要求。 - Alexander233
我甚至没有想过使用UUID生成器的输出作为元素名称,只是在元素中使用数据。你能给我一个这样做的例子吗?只是为了满足我的好奇心和无知? :-) - Dennis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接