代码之家  ›  专栏  ›  技术社区  ›  supercat

高效的二进制到字符串格式(如base64,但适用于UTF8/UTF16)?

  •  5
  • supercat  · 技术社区  · 14 年前

    我有许多二进制数据束,从16字节到4096字节不等,需要存储到数据库中,并且应该很容易作为一个单元进行比较(例如,只有在长度匹配且所有字节匹配的情况下,才有两束数据批处理)。字符串很好,但由于字符编码/重新解释问题,将二进制数据盲目转换为字符串容易导致问题。

    在7位ASCII为标准的年代,Base64是存储字符串的常用方法;它33%的空间损失有点恼人,但并不可怕。不幸的是,如果使用UTF-16,空间代价是166%(存储3个字节需要8个字节),这似乎很讨厌。

    是否有任何通用的存储方法可以将二进制数据存储在有效的Unicode字符串中,从而在UTF-16中实现更高的效率(希望在UTF-8中不会太可怕)?base-32768编码将在16个字符中存储240位,这将占用UTF-16的32字节或UTF-8的48字节。相比之下,base64编码将使用40个字符,这将占用UTF-16的80字节或UTF-8的40字节。设计用于在UTF-8或UTF-16中占用相同空间的方法可以在三个字符中存储48位,这将在UTF-8或UTF-16中占用8个字节,从而在UTF-8或UTF-16的40个字节中存储240位。

    这样的事情有什么标准吗?

    1 回复  |  直到 14 年前
        1
  •  6
  •   qntm    8 年前

    Base32768

    用法(这是JavaScript,尽管移植了 base32768 另一种编程语言的模块非常实用):

    var base32768 = require("base32768");
    
    var buf = new Buffer("d41d8cd98f00b204e9800998ecf842", "hex"); // 15 bytes
    
    var str = base32768.encode(buf); 
    console.log(str); // "迎裶垠⢀䳬Ɇ垙鸂", 8 code points
    
    var buf2 = base32768.decode(str);
    console.log(buf.equals(buf2)); // true
    

    Base32768从基本多语言平面中选择32768个字符。当表示为UTF-16时,每个字符需要2个字节,当表示为UTF-8时,每个字符需要3个字节,这恰好给出了您描述的效率特征:240位可以存储在16个字符中,即UTF-16的32个字节或UTF-8的48个字节。(除了偶尔的填充字符,类似于 = 在Base64中可以看到填充。)

    这是通过将输入字节(即8位无符号数)切成15位无符号数,并将得到的每个15位数字分配给32768个字符中的一个来实现的。

    请注意,选择的字符也是“安全的”——没有空格、控制字符、组合发音符号或易受规范化损坏。