(в .NET) У меня есть произвольные двоичные данные, хранящиеся в байте [] (например, изображение). Теперь мне нужно сохранить эти данные в строке (поле «Комментарий» старого API). Существует ли стандартная методика для упаковки этих двоичных данных в строку ? Под «упаковкой» я подразумеваю, что для любого достаточно большого и случайного набора данных байтов. Длина / 2 примерно равна pack.Length ; потому что два байта более или менее одного символа.
Два «очевидных» ответа не соответствуют всем критериям:
string base64 = System.Convert.ToBase64String(bytes)
не очень эффективно использует строку , поскольку она использует только 64 символа из примерно 60 000 доступных (мое хранилище - System.String ). Идя с
string utf16 = System.Text.Encoding.Unicode.GetString(bytes)
лучше использует строку , но она не будет работать для данных, которые содержат недопустимые символы Unicode (скажем, несовпадающие суррогатные пары). Эта статья MSDN показывает эту точную (плохую) технику.
Давайте рассмотрим простой пример:
byte[] bytes = new byte[] { 0x41, 0x00, 0x31, 0x00};
string utf16 = System.Text.Encoding.Unicode.GetString(bytes);
byte[] utf16_bytes = System.Text.Encoding.Unicode.GetBytes(utf16);
В этом случае байтов и utf16_bytes одинаковы, поскольку оригинальные байты были строкой UTF-16. Выполнение этой же процедуры с кодировкой base64 дает 16-членный base64_bytes массив.
Теперь повторите процедуру с неверными данными UTF-16:
byte[] bytes = new byte[] { 0x41, 0x00, 0x00, 0xD8};
Вы обнаружите, что utf16_bytes не соответствуют исходным данным.
Я написал код, который использует U + FFFD в качестве экранирования перед недопустимыми символами Юникода; это работает, но я хотел бы знать, есть ли более стандартная техника, чем то, что я только что приготовил самостоятельно. Не говоря уже о том, что catch не нравится DecoderFallbackException как способ обнаружения недопустимых символов.
Полагаю, вы могли бы назвать это кодировкой "базовый BMP" или "базовый UTF-16" (используя все символы в базовой многоязычной плоскости Unicode). Да, в идеале я бы следовал совету Шона Стила и передавал бы байт [] .
Я собираюсь согласиться с предложением Питера Хауса в качестве «правильного» ответа, потому что он единственный, кто приблизился к предложению «стандартной техники».
Редактировать base16k выглядит еще лучше. Джим Беверидж имеет реализацию .