【问题标题】:Alternatives to traditional algorithms for encoding UUIDS (e.g. Base32, Base62)用于编码 UUIDS 的传统算法的替代方案(例如 Base32、Base62)
【发布时间】:2011-07-07 06:41:34
【问题描述】:

我们需要将大量的 UUID 转换为与 xml 兼容的字符串。如果我们使用 Base32 算法(将每 5 位映射到 32 个字符之一),这将导致 26 个字符字符串,如果我们使用 Base62 算法(迭代地将 128 位整数除以 62 并将模数记录为 62 个字符之一) 这导致 22 个字符字符串。虽然 base62 返回较短的字符串,但它对 cpu 的占用率更高,因此我们坚持使用 Base32(Base64 不是一个选项,因为 xml)。

您知道任何其他类型的编码算法可以帮助我们吗?是否有类似 Base32 的位模式编码算法的变体可以与不是 2 的幂的基一起使用?或者是否有混合算法将第一个算法的方法与第二个算法的方法结合起来?如果可能,我们希望将 char 字符串减少到少于 26 个。

【问题讨论】:

    标签: algorithm guid uuid


    【解决方案1】:

    您提到了 62,这表明您将字母表限制为 A-Z(大写和小写)和数字 0-9。为什么不在该列表中添加另外几个与 XML 兼容的字符,例如 +.~!,以使该数字达到 64?您将能够进行位移而不是除法,这将使算法与 Base32 算法一样快并减少字符串大小。

    编辑:由于限制这些字符也可用于其他尚未指定的语言,您可能需要转义一些字符以表示您的 64 个选项。例如,如果您使用 _ 作为转义字符,您可以让 _1 和 _2 代表选项 63 和 64。原始问题中提到的统计数据表明 UUIDS 是 128 位的,所以如果有,我们的 Base64 会给我们 22 个字符没有转义,并且最多有 4 个项目被转义,保持在 26 个字符内。

    【讨论】:

    • 好点,谢谢!但是 XML 对我们来说并不是唯一的限制,我们还需要在某些编程语言中使用它来生成类名(下划线可能是另一个字符,但我找不到第 64 个可用的 ASCII 字符)。跨度>
    • @Carina - 我添加了一个建议,重新转义,如果你的字符用完了,这可能会有所帮助。你最好 - 如果可以的话 - 找到你额外的第 64 个字符。
    • 您可能已经想到了这一点,但也意识到大多数语言不允许类名以数字开头。因此,您可能还应该在所有这些前缀上加上一些合法字符。
    【解决方案2】:

    维基百科提供了两个可用于 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;
    }
    

    }

    【讨论】:

    • 非常有趣。但是您在 XML 中提到的方法的问题是元素名称可能不以数字开头,并且可能不以“xml”或“XML”开头。维基百科文章的方法和 base64URLSafeOfUUIDObject 都会导致一些不符合这些要求的编码。
    • 我什至没有想过使用 UUID 生成器的输出作为元素的名称,只使用元素中的数据。你能给我一个这样做的例子吗?只是为了满足我的好奇心和无知? :-)
    猜你喜欢
    • 1970-01-01
    • 2013-05-01
    • 2019-11-18
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多