Подтвердить что ты не робот

Confused о С++ std:: wstring, UTF-16, UTF-8 и отображении строк в графическом интерфейсе Windows

Я работаю только на англоязычной программе на С++ для Windows, где нам сказали "всегда использовать std:: wstring", но похоже, что у кого-то в команде действительно есть много понимания, кроме этого.

Я уже прочитал вопрос под названием std:: wstring VS std::string. Это было очень полезно, но я до сих пор не совсем понимаю, как применять все этой информации к моей проблеме.

Программа, над которой я работаю, отображает данные в графическом интерфейсе Windows. Эти данные сохраняются как XML. Мы часто трансформируем этот XML с помощью XSLT в HTML или XSL: FO для целей отчетности.

Мое чувство, основанное на том, что я прочитал, заключается в том, что HTML должен быть закодирован как UTF-8. Я очень мало знаю о разработке графического интерфейса, но маленький бит, который я прочитал, указывает на то, что весь файл GUI основан на закодированных строках UTF-16.

Я пытаюсь понять, где это оставляет меня. Скажем, мы решили, что все наши постоянные данные должны быть закодированы в формате UTF-8. Означает ли это, что для отображения сохраняемых данных в компоненте пользовательского интерфейса я должен действительно выполнять какой-то явный процесс перекодирования UTF-8 в UTF-16?

Я подозреваю, что мое объяснение может использовать пояснения, поэтому я постараюсь предоставить, если у вас есть какие-либо вопросы.

4b9b3361

Ответ 1

Windows начиная с NT4 основана на Unicode-кодированных строках, да. Ранние версии были основаны на UCS-2, который является предшественником UTF-16, и, следовательно, не поддерживает все символы, которые поддерживает UTF-16. Более поздние версии основаны на UTF-16. Однако не все ОС основаны на UTF-16/UCS-2. * Системы nix, например, основаны на UTF-8.

UTF-8 - очень хороший выбор для постоянного хранения данных. Это универсально поддерживаемая кодировка во всех средах Unicode, и это хороший баланс между размером данных и совместимостью данных без потерь.

Да, вам придется анализировать XML, извлекать из него необходимую информацию, декодировать и преобразовывать его в то, что может использовать пользовательский интерфейс.

Ответ 2

AFAIK, когда вы работаете с std:: wstring в Windows на С++ и сохраняете файлы UTF-8 в файлах (что звучит неплохо и разумно), вам необходимо преобразовать данные в UTF-8 при записи в файл и конвертируйте обратно в UTF-16 при чтении из файла. Проверьте эту ссылку: Написание файлов UTF-8 на С++.

Я бы придерживался стандартного проекта Visual Studio → Свойства → Свойства конфигурации → Общие → Набор символов → Использовать набор символов Юникода, используйте тип wchar_t (т.е. с помощью std:: wstring), а не используйте Тип TCHAR. (Например, я бы просто использовал wcslen версию strlen, а не _tcslen.)

Ответ 3

std:: wstring - это технически UCS-2: для каждого символа используются два байта, а таблицы кодов в основном отображаются в формате Unicode. Важно понимать, что UCS-2 - это не то же самое, что UTF-16! UTF-16 позволяет "суррогатные пары", чтобы представлять символы, находящиеся за пределами двухбайтового диапазона, но UCS- 2 использует ровно два байта для каждого символа, периода.

Лучшим правилом для вашей ситуации является перекодирование при чтении и записи на диск. После этого в памяти сохраните его в формате UCS-2. API Windows будет читать его, как если бы это был UTF-16 (то есть, в то время как std:: wstring не понимает концепцию суррогатных пар, если вы их вручную создаете (чего вы не будете, если ваш единственный язык Русский), Windows их прочитает).

Всякий раз, когда вы читаете данные в форматах сериализации (например, XML) или в них, в современный день, вам, вероятно, придется перекодировать. Это неприятный и очень неудачный факт жизни, но неизбежный, поскольку Unicode представляет собой кодировку символов переменной ширины, и большинство операций на основе символов в С++ выполняются как массивы, для которых требуется согласованное расстояние.

Структуры более высокого уровня, такие как .NET, скрывают большую часть деталей, но за кулисами они обрабатывают транскодирование таким же образом: изменение данных переменной ширины в строки фиксированной ширины, их манипулирование и затем, если это требуется для вывода, они будут заменены на кодировки переменной ширины.

Ответ 4

Одно из преимуществ использования std:: wstring в Windows для строк, связанных с GUI, заключается в том, что внутренне все вызовы Windows API используют и работают на UTF-16. Если вы когда-либо заметили, есть две версии всех вызовов Win32 API, которые принимают строковые аргументы. Например, "MessageBoxA" и "MessageBoxW". Оба определения существуют и фактически вы можете вызывать либо вы хотите, но если он включен в поддержку Unicode, то произойдет следующее:

#define MessageBox MessageBoxW

Затем вы попадаете в TCHAR и другие трюки Microsoft, чтобы попытаться упростить работу с API, имеющими как ANSI, так и Unicode-версию. Короче говоря, вы можете позвонить либо, но под капотом ядра Windows в формате Unicode, поэтому вы будете платить стоимость конвертации в Unicode для каждой строки, принимающей вызов Win32 API, если вы не используете широкую версию char.

UTF-16 и использование ядра Windows

Ответ 5

Даже если вы говорите, что у вас есть только английский язык, вы, вероятно, ошибаетесь. Поскольку мы сейчас находимся в глобальном мире, имена/адреса/etc имеют иностранные символы. Хорошо, я не знаю, какой тип данных у вас есть, но, как правило, я бы сказал, создайте приложение для поддержки UNICODE для хранения данных и отображения данных для пользователя. Это предполагает использование XML с UTF-8 для хранения и UNICODE-версий вызовов Windows, когда вы выполняете GUI. И поскольку в графическом интерфейсе Windows используется UTF-16, где каждый токен - 16 бит, я бы предложил хранить данные в приложении в 16-битной строке. И я бы предположил, что ваш компилятор для окон будет иметь std:: wstring как 16-бит для этой цели.

Итак, вам нужно сделать много конверсий между UTF-16 и UTF-8. Сделайте это с помощью некоторой существующей библиотеки, например ICU.