2012-06-28 2 views
8

В настоящее время я работаю над проектом хобби (C/C++), который должен работать как на Windows, так и на Linux, с полной поддержкой Unicode. К сожалению, Windows и Linux используют разные кодировки, что усложняет нашу жизнь.Кросс-платформенный юникод в C/C++: какую кодировку использовать?

В моем коде я пытаюсь использовать данные как можно более универсальные, что упрощает работу как для Windows, так и для Linux. В Windows wchar_t по умолчанию кодируется как UTF-16, а как UCS-4 в Linux (исправьте меня, если я ошибаюсь).

Мое программное обеспечение открывается ({_wfopen, UTF-16, Windows}, {fopen, UTF-8, Linux}) и записывает данные в файлы в UTF-8. Пока все это выполнимо. Пока я не решил использовать SQLite.

Интерфейс SQLite C/C++ допускает одно- или двухбайтовые закодированные строки (click). Конечно, это не работает с wchar_t в Linux, так как wchar_t в Linux по умолчанию составляет 4 байта. Поэтому для записи и чтения из sqlite требуется преобразование для Linux.

В настоящее время код загромождает исключениями для Windows/Linux. Я надеялся, что придерживаться стандартной идеи хранения данных в wchar_t:

  • wchar_t в Windows: Пути к файлам без проблем, чтение/запись к SQLite без проблем. Запись данных в файл должна выполняться в UTF-8 в любом случае.
  • wchar_t в Linux: исключение для путей к файлу из-за кодировки UTF-8, преобразование перед чтением/записью в sqlite (wchar_t) и то же самое для окон при записи данных в файл.

После прочтения (here) Я был убежден, что должен придерживаться wchar_t в Windows. Но после того, как все это сработало, проблема началась с портирования в Linux.

В настоящее время я собираюсь переделать все, чтобы придерживаться простого символа (UTF-8), потому что он работает как с Windows, так и с Linux, учитывая тот факт, что мне нужна «WideCharToMultiByte» каждая строка в Windows для достижения UTF-8. Использование простых символов на основе char * значительно уменьшит количество исключений для Linux/Windows.

Есть ли у вас опыт работы с unicode для кросс-платформенного? Любые мысли о идее простого хранения данных в UTF-8 вместо использования wchar_t?

+0

2 байта кодировка символов определенно * нет * UTF-16.UTF-16 - от 2 до 4 байтов, а UTF-8 - 1 - 4 байта. Windows 'wchar_t' не UTF-16, это UCS2. На практике вы можете не заметить разницу, потому что UCS2 охватывает BMP, но если когда-либо ваши пользователи решат, что у них должны быть данные в Ogham или рунах ... – user268396

+1

Windows использует UTF-16 и использует 'wchar_t' для хранения UTF-16 данных и сделал это с Windows 2000. –

+3

О том, насколько полезен wchar_t и для чего: http://stackoverflow.com/a/11107667/365496 – bames53

ответ

6

UTF-8 на всех платформах с преобразованием точно в срок в UTF-16 для Windows - обычная тактика для кросс-платформенного Unicode.

+0

Я бы немного подкорректировал этот оператор и сказал: «Нативная кодировка на всех платформах», с преобразованием «точно в срок» в/из UTF-8. Требуется преобразование «точно в срок», когда символьные строки покидают приложение (например, записываются в файл, отправляются данные через сетевой сокет, передаются данные в библиотеку и т. Д.). Конечно, все зависит от конкретного сценария. – IInspectable

2

Наше программное обеспечение также является кросс-платформенным, и мы столкнулись с аналогичными проблемами. Мы решили, что наша цель - обеспечить наименьшее количество конверсий. Это означает, что мы используем wchar_t для Windows и char на Unix/Mac.

Мы делаем это, поддерживая _T и LPCTSTR и похоже на Unix и имеющих общие функции, которые легко конвертировать между std::string и std::wstring. У нас также есть общий std::basic_string<TCHAR> (tstring), который мы используем в большинстве случаев.

Пока это работает достаточно хорошо. В основном большинство функций принимают tstring или LPCTSTR, а те, которые не будут преобразовывать их параметры из tstring. Это означает, что большую часть времени мы не конвертируем наши строки и не пропускаем большинство параметров.

+2

Это тоже возможное решение, но все же немного хаки. Кроме того, из моего чтения я узнал, что мне следует избегать использования TCHAR, поскольку он был введен для поддержки обратной совместимости со старым программным обеспечением, переключаясь на MBCS вместо флага Unicode. – ErikKou

+0

@Fozi, Как мне поддерживать _T на Ubuntu Linux? Большое спасибо. – Frank

+0

@ErikKou, Каково ваше возможное решение для эмуляции макроса Windows _T в Unix или Linux? Спасибо. – Frank