Что я должен использовать?UTF8 или UTF16? - PullRequest
17 голосов
/ 22 марта 2012

Я должен распространять свое приложение на международном уровне.

Допустим, у меня есть элемент управления (например, памятка), в который пользователь вводит какой-то текст. Пользователь может быть японским, русским, канадским и т. Д. Я хочу сохранить строку на диск как файл TXT для дальнейшего использования. Я буду использовать МОЮ СОБСТВЕННУЮ функцию для записи текста, а не что-то вроде TMemo.SaveToFile ().

Как мне сохранить строку на диск? В формате UTF8 или UTF16?

Ответы [ 3 ]

30 голосов
/ 22 марта 2012

Основное различие между ними заключается в том, что UTF8 обратно совместим с ASCII. Пока вы используете только первые 128 символов, приложение, которое не поддерживает Unicode, может обрабатывать данные (что может быть преимуществом или недостатком, в зависимости от вашего сценария). В частности, при переключении на UTF16 каждую функцию API необходимо настроить для 16-битных строк, в то время как с UTF8 вы часто можете оставить старые функции API без изменений, если они не выполняют какой-либо обработки строк. Также UTF8 не зависит от порядка байтов, в то время как UTF16 делает, что может усложнить ввод / вывод строки.

Распространенным заблуждением является то, что UTF16 легче обрабатывать, поскольку каждый символ всегда занимает ровно два байта. Это, к сожалению, не соответствует действительности. UTF16 - это кодирование переменной длины, где символ может занимать 2 или 4 байта. Таким образом, любые трудности, связанные с UTF8 в отношении проблем переменной длины, применимы и к UTF16.

Наконец, размеры хранилища. Еще один распространенный миф об UTF16 заключается в том, что он более эффективен в хранении, чем UTF8 для большинства иностранных языков. UTF8 занимает меньше памяти для всех европейских языков, которая может быть закодирована одним или двумя байтами на символ. Не-BMP символы занимают 4 байта как в UTF8, так и в UTF16. Единственный случай, когда UTF16 занимает меньше места, - это если ваш текст в основном состоит из символов в диапазоне от U + 0800 до U + FFFF, где хранятся символы для китайского, японского и хинди.

Джеймс МакНеллис выступил с превосходной речью на BoostCon 2014, подробно обсудив различные компромиссы между различными кодировками. Несмотря на то, что доклад называется Unicode в C ++ , вся первая половина фактически не зависит от языка. Видеозапись полного выступления доступна на канале Boostcon Youtube , а слайды можно найти на github .

27 голосов
/ 22 марта 2012

Зависит от языка ваших данных.

Если ваши данные в основном на западных языках, и вы хотите уменьшить объем необходимого хранилища, используйте UTF-8, поскольку для этих языков потребуется около половины хранилища UTF-16. Вы будете платить штраф при чтении данных, так как они будут / должны быть преобразованы в UTF-16, который является Windows по умолчанию и используется строкой Delphi (Unicode).

Если ваши данные в основном не на западных языках, UTF-8 может занимать больше памяти, чем UTF-16, поскольку для некоторых может занимать до 6 4 байт на символ , (см. комментарий @KennyTM)

В основном: проведите несколько тестов с репрезентативными образцами данных ваших пользователей и посмотрите, какие из них работают лучше, как с точки зрения требований к хранилищу, так и времени загрузки. У нас были некоторые сюрпризы с медленным UTF-16, чем мы думали. Прирост производительности, связанный с отсутствием необходимости преобразования из UTF-8 в UTF-16, был потерян из-за доступа к диску, поскольку объем данных в UTF-16 больше.

10 голосов
/ 22 марта 2012

Прежде всего, имейте в виду, что стандартная кодировка под Windows - UCS2 (до Windows 2000) или UTF-16 (начиная с XP), и что собственный тип "string" Delphi использует тот же собственный формат, начиная с Delphi 2009 (string=UnicodeString char=WideChar).

Во всех случаях небезопасно принимать 1 WideChar == 1 символ Юникода - это проблема суррогат .

О программеВыбор UTF-8 или UTF-16, это зависит от самого хранилища:

  • Если ваш файл представляет собой простой текстовый файл (включая XML), вы можете использовать либо UTF-8или UTF-16 - но вам придется использовать спецификацию в начале файла, в противном случае приложения (например, Блокнот) могут запутаться при открытии - для XML это обрабатывается вашей библиотекой (если этонет, перейдите на другую библиотеку);
  • Если вы уверены, что ваш контент в основном является 7-битным ASCII, используйте UTF-8 и связанную с ним спецификацию;
  • Если ваш файл какой-тотип базы данных или пользовательский двоичный формат , безусловно, лучший формат - UTF-16 /UCS2, то есть макет Delphi 2009+ string по умолчанию и, конечно, макет API базы данных по умолчанию;
  • Некоторые форматы файлов требуют или предпочитают UTF-8 (например, JSON или даже SQLite3 ), даже если файлы UTF-8 могут быть больше, чем UTF-16 для азиатских символов.

Например, мы использовали UTF-8 для нашей инфраструктуры клиент-сервер, поскольку мы используем JSON в качестве формата обмена (для которого требуется UTF-8), а поскольку SQlite3 нравится UTF-8.Конечно, нам пришлось написать несколько специализированных функций и классов, чтобы избежать преобразования в / из string (что медленно для типа string=UnicodeString начиная с Delphi 2009 и может потерять некоторые данные при использовании с типом string=AnsiString до Delphi).2009. См. этот пост и этот блок ).Самый простой - полагаться на тип string=UnicodeString, использовать функции RTL, которые непосредственно обрабатывают кодировку UTF-16, и избегать преобразований.И не забудьте о вашем предыдущем вопросе .

Если дисковое пространство и скорость чтения / записи являются проблемой, рассмотрите возможность использования сжатия вместо изменения кодировки.Существует сжатие в реальном времени (быстрее, чем ZIP), например, LZO или SynLZ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...