Строки С++: UTF-8 или 16-битная кодировка?

Я все еще пытаюсь решить, должен ли мой (домашний) проект использовать UTF-8. строки (реализованные в терминах std::string с дополнительными функциями, специфичными для UTF-8, когда это необходимо) или некоторые 16-битные строки (реализованные как std::wstring). Проект представляет собой язык программирования и среду (как и VB, это комбинация того и другого).

Есть несколько пожеланий/ограничений:

  • Было бы здорово, если бы он мог работать на ограниченном оборудовании, например, на компьютерах с ограниченным объемом памяти.
  • Я хочу, чтобы код работал на Windows, Mac и (если позволяют ресурсы) Linux.
  • Я буду использовать wxWidgets в качестве слоя графического интерфейса, но я хочу, чтобы код, взаимодействующий с этим набором инструментов, был заключен в угол кодовой базы (у меня будут исполняемые файлы без графического интерфейса).
  • Я хотел бы избежать работы с двумя разными типами строк при работе с видимым пользователем текстом и с данными приложения.

В настоящее время я работаю с std::string с намерением использовать функции манипулирования UTF-8 только при необходимости. Для этого требуется меньше памяти, и, похоже, именно в этом направлении идут многие приложения.

Если вы рекомендуете 16-битную кодировку, какую: UTF-16? UCS-2? Еще один?


person Carl Seleborg    schedule 19.09.2008    source источник
comment
Micro ATX не означает ограниченный объем памяти. Мой домашний ПК работает на ASUS M2A-VM (Micro-ATX), и Crysis работает нормально.   -  person davidtbernal    schedule 24.08.2010
comment
Я отредактировал вопрос, чтобы удалить ошибку.   -  person Delan Azabani    schedule 12.08.2011


Ответы (8)


Я бы рекомендовал UTF-16 для любых манипуляций с данными и пользовательского интерфейса. Mac OS X и Win32 API используют UTF-16, то же самое для wxWidgets, Qt, ICU, Xerces и других. UTF-8 может быть лучше для обмена и хранения данных. См. http://unicode.org/notes/tn12/.

Но что бы вы ни выбрали, я определенно рекомендую не использовать std::string с UTF-8 «только при необходимости».

Пройдите весь путь с UTF-16 или UTF-8, но не смешивайте и не совмещайте, это напрашивается на неприятности.

person user19050    schedule 19.09.2008
comment
Программист Mac из моей команды говорит, что wchar_t — 32 бита. И, безусловно, в нашей кодовой базе много кода, который в противном случае сломался бы. - person MSalters; 22.09.2008
comment
Просто для уточнения: с utf-8 только при необходимости, я на самом деле имел в виду, что буду использовать некоторые функции манипуляции с utf-8 только тогда, когда мне действительно нужно иметь дело с символами, но все строки всегда будут utf -8. - person Carl Seleborg; 23.09.2008
comment
Принято: я хочу четкого разделения между графическим интерфейсом и доменами данных. Последнее будет связано с обменом и хранением, поэтому я не возражаю против преобразования уровня графического интерфейса в utf-16 wxStrings из объектов std::string, закодированных в utf-8. - person Carl Seleborg; 23.09.2008
comment
Возможно, вы захотите прочитать этот вопрос об UTF-16: stackoverflow.com/questions/1049947/ - person davidtbernal; 24.08.2010

UTF-16 по-прежнему является кодировкой символов переменной длины (существует более 2 ^ 16 кодовых точек Unicode), поэтому вы не можете выполнять операции индексации строк O (1). Если вы делаете много подобных вещей, вы ничего не экономите в скорости по сравнению с UTF-8. С другой стороны, если ваш текст включает много кодовых точек в диапазоне 256-65535, UTF-16 может существенно увеличить размер. UCS-2 — это разновидность UTF-16, которая имеет фиксированную длину за счет запрета любых кодовых точек больше 2^16.

Не зная больше о ваших требованиях, я бы лично выбрал UTF-8. С ним проще всего иметь дело по всем причинам, которые уже перечислили другие.

person Nick Johnson    schedule 19.09.2008

Честно говоря, я никогда не находил причин использовать что-то еще, кроме UTF-8.

person Vargen    schedule 19.09.2008

Если вы решили использовать кодировку UTF-8, проверьте эту библиотеку: http://utfcpp.sourceforge.net/

Это может сделать вашу жизнь намного проще.

person Nemanja Trifunovic    schedule 19.09.2008

На самом деле я написал широко используемое приложение (более 5 миллионов пользователей), поэтому каждый используемый килобайт буквально складывается. Несмотря на это, я просто придерживался wxString. Я настроил его так, чтобы он производился от std::wstring, поэтому я могу передавать их функциям, ожидающим константу wstring&.

Обратите внимание, что std::wstring — это родной Unicode на Mac (для символов выше U+10000 не требуется UTF-16), и поэтому он использует 4 байта/wchar_t. Большим преимуществом этого является то, что i++ всегда дает вам следующий символ. На Win32 это верно только в 99,9% случаев. Как коллега-программист, вы поймете, как мало 99,9%.

Но если вы не уверены, напишите функцию в верхнем регистре для std::string[UTF-8] и std::wstring. Эти 2 функции скажут вам, какой путь является безумием.

Ваш формат на диске - другое дело. Для переносимости это должно быть UTF-8. В UTF-8 нет проблем с порядком байтов и не обсуждается ширина (2/4). Возможно, поэтому многие программы используют UTF-8.

В немного не связанной с этим заметке, пожалуйста, прочитайте сравнение строк Unicode и нормализацию. Или вы получите ту же ошибку, что и .NET, где у вас могут быть две переменные föö и föö, отличающиеся только (невидимой) нормализацией.

person MSalters    schedule 21.09.2008
comment
Обратите внимание, что при использовании UTF32 на Mac используется много памяти. Упомянутый вами случай 0,1% означает, что любая wstring на Mac будет вдвое больше, чем та же строка в UTF16 в Windows (я даже не буду упоминать char в Linux). Это является одной из причин, по которой Linux использует символ UTF-8, и почему Windows использует wchar_t UTF-16. - person paercebal; 22.09.2008

MicroATX — это в значительной степени стандартный формат материнской платы для ПК, наиболее способный к 4-8 ГБ ОЗУ. Если вы говорите о picoATX, возможно, вы ограничены 1-2 ГБ ОЗУ. Но даже этого достаточно для среды разработки. Я бы по-прежнему придерживался UTF-8 по причинам, упомянутым выше, но память не должна вас беспокоить.

person basszero    schedule 19.09.2008
comment
@Peter Mortensen: А, спасибо. Не знал о такой функции. - person Patrick Niedzielski; 24.08.2010

Из того, что я прочитал, лучше использовать 16-битную кодировку внутри, если у вас не хватает памяти. Он подходит почти ко всем живым языкам в одном символе.

Я бы также посмотрел на ICU. Если вы не собираетесь использовать определенные функции строк STL, вам может быть лучше использовать типы строк ICU.

person Branan    schedule 19.09.2008
comment
На самом деле, UTF-16 умещает большинство символов живого языка в двух байтах; взгляните на [таблицы кодовых точек][unicode.org/charts/PDF/] для кодовых точек выше U+10000; все это древнегреческие или римские символы. - person Ben Straub; 20.09.2008

Рассматривали ли вы возможность использования wxStrings? Если я правильно помню, они могут выполнять преобразования utf-8 ‹-> Unicode, и это немного упростит задачу, когда вам нужно передавать строки в пользовательский интерфейс и из него.

person Ferruccio    schedule 19.09.2008