Использование UTF в коде C++
В чем разница между UTF и UCS.
Каковы наилучшие способы представления не европейских наборов символов (с использованием UTF) в строках C++. Я хотел бы знать ваши рекомендации для:
- Внутреннее представление внутри кода
- Для работы со строками во время выполнения
- Для использования строки в целях отображения.
- Лучшее представление хранилища (т.е. в файле)
- Лучший формат передачи по проводам (передача между приложениями, которые могут быть на разных архитектурах и иметь разные стандартные локали)
5 ответов
В чем разница между UTF и UCS.
Кодировки UCS имеют фиксированную ширину и отмечены тем, сколько байтов используется для каждого символа. Например, UCS-2 требует 2 байта на символ. Символы с кодовыми точками за пределами доступного диапазона не могут быть закодированы в кодировке UCS.
Кодировки UTF имеют переменную ширину и отмечены минимальным количеством битов для хранения символа. Например, UTF-16 требует по меньшей мере 16 бит (2 байта) на символ. Символы с большими кодовыми точками кодируются с использованием большего количества байтов - 4 байта для астральных символов в UTF-16.
- Внутреннее представление внутри кода
- Лучшее представление хранилища (т.е. в файле)
- Лучший формат передачи по проводам (передача между приложениями, которые могут быть на разных архитектурах и иметь разные стандартные локали)
Для современных систем наиболее приемлемым кодированием хранения и транспорта является UTF-8. Существуют особые случаи, когда могут подойти другие - UTF-7 для старых почтовых серверов, UTF-16 для плохо написанных текстовых редакторов - но UTF-8 является наиболее распространенным.
Предпочтительное внутреннее представление будет зависеть от вашей платформы. В Windows это UTF-16. В UNIX это UCS-4. У каждого есть свои плюсы:
- Строки UTF-16 никогда не используют больше памяти, чем строка UCS-4. Если вы храните много больших строк с символами, в основном в базовой многоязычной плоскости (BMP), UTF-16 потребует гораздо меньше места, чем UCS-4. За пределами BMP он будет использовать то же количество.
- UCS-4 легче рассуждать. Поскольку символы UTF-16 могут быть разделены на несколько "суррогатных пар", может возникнуть проблема с правильным разделением или отображением строки. Текст UCS-4 не имеет этой проблемы. UCS-4 также действует подобно тексту ASCII в массивах "char", поэтому существующие текстовые алгоритмы могут быть легко перенесены.
Наконец, некоторые системы используют UTF-8 в качестве внутреннего формата. Это хорошо, если вам необходимо взаимодействовать с существующими системами на основе ASCII или ISO-8859, поскольку байты NULL отсутствуют в середине текста UTF-8 - они находятся в UTF-16 или UCS-4.
Читали ли вы статью Джоэла Спольски " Абсолютный минимум", который должен знать каждый разработчик программного обеспечения Абсолютно, положительно должен знать о Юникоде и наборах символов (без оправданий!)?
Я бы предложил:
- Для представления в коде,
wchar_t
или эквивалент. - Для представления памяти, UTF-8.
- Для представления проводов, UTF-8.
Преимущество UTF-8 в складских и проводных ситуациях заключается в том, что машинный ресурс не имеет значения. Преимущество использования символа фиксированного размера, такого как wchar_t
в коде это то, что вы можете легко узнать длину строки без необходимости ее сканирования.
Во внутреннем представлении внутри кода лучше сделать это для европейских и неевропейских символов:
\ uNNNN
Символы в диапазоне от \u0020 до \u007E и небольшой пробел (например, конец строки) могут быть записаны как обычные символы. Все, что выше \u0080, если вы напишите его как обычный символ, оно будет скомпилировано только на вашей кодовой странице (например, "Хорошо во Франции, но в России, в России, в Японии, в Китае, в США и т. Д.")..).
UTC - это Всемирное координированное время, а не набор символов (я не нашел ни одной кодировки под названием UTC).
Для внутреннего представительства вы можете использовать wchar_t
для каждого символа и std::wstring для строк. Они используют ровно 2 байта для каждого символа, поэтому поиск и произвольный доступ будут быстрыми.
Для хранения, если большая часть данных не является ASCII (т. Е. Код>= 128), вы можете использовать UTF-16, который почти совпадает с сериализованным wstring
а также wchar_t
,
Поскольку для проводного транспорта UTF-16 может иметь порядок с прямым или обратным порядком байтов, попробуйте преобразовать его в UTF-8, который не зависит от архитектуры.