Что я должен использовать? UTF8 или UTF16? - программирование
Подтвердить что ты не робот

Что я должен использовать? UTF8 или UTF16?

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

Скажем, у меня есть элемент управления (например, заметка), где пользователь вводит какой-либо текст. Пользователь может быть японским, русским, канадским и т.д. Я хочу сохранить строку на диске в виде файла TXT для последующего использования. Я буду использовать функцию MY OWN для написания текста, а не что-то вроде TMemo.SaveToFile().

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

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

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