Эффективное двоичное форматирование (как base64, но для UTF8 / UTF16)? - PullRequest
5 голосов
/ 22 октября 2010

У меня много пакетов двоичных данных, размером от 16 до 4096 байт, которые необходимо сохранить в базе данных и которые легко сопоставимы как единица измерения (например, две группы данных, только если совпадают длины и все байты)матч).Строки хороши для этого, но преобразование двоичных данных вслепую в строку склонно вызывать проблемы из-за проблем кодирования / реинтерпретации символов.

Base64 был распространенным методом для хранения строк в эпоху, когда 7-битный ASCII былнорма;его 33% -ое космическое наказание было немного раздражающим, но не ужасным.К сожалению, если кто-то использует UTF-16, размер дискового пространства составляет 166% (8 байт для хранения 3), что выглядит довольно странно.

Существует ли какой-либо общий способ хранения для хранения двоичных данных в допустимой строке Unicode, которыйПозволит ли лучшая эффективность в UTF-16 (и, надеюсь, не будет слишком ужасной в UTF-8)?Кодирование base-32768 будет хранить 240 битов в шестнадцати символах, что займет 32 байта UTF-16 или 48 байтов UTF-8.Для сравнения, кодирование base64 будет использовать 40 символов, что займет 80 байтов UTF-16 или 40 байтов UTF-8.Подход, который был разработан для того, чтобы занимать одно и то же пространство в UTF-8 или UTF-16, может хранить 48 бит в трех символах, которые будут занимать восемь байтов в UTF-8 или UTF-16, таким образом, сохраняя 240 бит в 40 байтах любого UTF.-8 или UTF-16.

Существуют ли стандарты для чего-либо подобного?

1 Ответ

3 голосов
/ 19 апреля 2016

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 выбирает 32 768 символов изБазовая многоязычная плоскость.Каждый символ занимает 2 байта, когда он представлен как UTF-16, или 3 байта, когда он представлен как UTF-8, что дает именно те характеристики эффективности, которые вы описываете: 240 бит могут быть сохранены в 16 символах, т.е. 32 байта UTF-16 или 48 байтов UTF-.8.(За исключением случайного символа заполнения, аналогичного заполнению = в Base64.)

Это делается путем разбиения входных байтов (то есть 8-разрядных чисел без знака) на 15-разрядные числа без знака и назначениякаждое получающееся 15-разрядное число соответствует одному из 32 768 символов.

Обратите внимание, что выбранные символы также являются "безопасными" - без пробелов, управляющих символов, сочетания диакритических знаков или подверженности повреждению нормализации.

...