Ответ 1
То же, что и ответ Адама Розенфилда (+1), но вместо этого я использую UTFCPP.
Я знаю, что в StackOverflow уже есть несколько вопросов о std::string
versus std::wstring
или аналогичных, но ни одно из них не предложило полного решения.
Чтобы получить хороший ответ, я должен определить требования:
CFStringRef
, wchar_t *
, char*
как UTF-8 или других типов, как того требует OS API. Примечание. Мне не нужна поддержка конвертации кода кода, потому что я ожидаю использовать только совместимые с Unicode функции во всех поддерживаемых операционных системах.Я бы по достоинству оценил только одно предлагаемое решение за каждый ответ, делая это, люди могут голосовать за свою предпочтительную альтернативу. Если у вас несколько альтернатив, просто добавьте еще один ответ.
Просьба указать что-то, что действительно сработало для вас.
Похожие вопросы:
То же, что и ответ Адама Розенфилда (+1), но вместо этого я использую UTFCPP.
Я настоятельно рекомендую использовать UTF-8 внутри вашего приложения, используя обычные старые char*
или std::string
для хранения данных. Для взаимодействия с API, использующими другую кодировку (ASCII, UTF-16 и т.д.), Я бы рекомендовал использовать libiconv, что лицензирован под LGPL.
Пример использования:
class TempWstring
{
public:
TempWstring(const char *str)
{
assert(sUTF8toUTF16 != (iconv_t)-1);
size_t inBytesLeft = strlen(str);
size_t outBytesLeft = 2 * (inBytesLeft + 1); // worst case
mStr = new char[outBytesLeft];
char *outBuf = mStr;
int result = iconv(sUTF8toUTF16, &str, &inBytesLeft, &outBuf, &outBytesLeft);
assert(result == 0 && inBytesLeft == 0);
}
~TempWstring()
{
delete [] mStr;
}
const wchar_t *Str() const { return (wchar_t *)mStr; }
static void Init()
{
sUTF8toUTF16 = iconv_open("UTF-16LE", "UTF-8");
assert(sUTF8toUTF16 != (iconv_t)-1);
}
static void Shutdown()
{
int err = iconv_close(sUTF8toUTF16);
assert(err == 0);
}
private:
char *mStr;
static iconv_t sUTF8toUTF16;
};
iconv_t TempWstring::sUTF8toUTF16 = (iconv_t)-1;
// At program startup:
TempWstring::Init();
// At program termination:
TempWstring::Shutdown();
// Now, to convert a UTF-8 string to a UTF-16 string, just do this:
TempWstring x("Entr\xc3\xa9""e"); // "Entrée"
const wchar_t *ws = x.Str(); // valid until x goes out of scope
// A less contrived example:
HWND hwnd = CreateWindowW(L"class name",
TempWstring("UTF-8 window title").Str(),
dwStyle, x, y, width, height, parent, menu, hInstance, lpParam);
Недавно я был в проекте, который решил использовать std:: wstring для кросс-платформенного проекта, потому что "широкие строки - это Unicode, правильно?" Это привело к ряду головных болей:
Когда вы используете код, специфичный для платформы, имеет смысл использовать собственное представление платформы для связи с его API. Но для любого кода, который используется на разных платформах или обменивается между платформами, избегайте всей двусмысленности и используйте UTF-8.
Правило большого пальца: используйте форму платформы Unicode для обработки (UTF-16 или UTF-32) и UTF-8 для обмена данными (связь, хранение).
Если все пользовательские API используют UTF-16 (например, в Windows), то ваши строки как UTF-8 означают, что вам нужно будет преобразовать все входные данные в UTF-16, вызвать Win API, а затем преобразовать ответ в UTF -8. Очень боль.
Но если главной проблемой является пользовательский интерфейс, то строки являются простой проблемой. Более сложным является структура пользовательского интерфейса. И для этого я бы рекомендовал wxWidgets (http://www.wxWidgets.org). Поддерживает многие платформы, зрелые (17 лет и все еще очень активные), собственные виджеты, Unicode, либеральная лицензия.
Я бы пошел на представление UTF16 в памяти и UTF-8 или 16 на жесткий диск или провод. Основная причина: UTF16 имеет фиксированный размер для каждой "буквы". Это упрощает много обязанностей при работе со строкой (серификация, замена частей,...).
Единственная причина для UTF-8 - сокращение использования памяти для "западных/латинских" букв. Вы можете использовать это представление для хранения диска или транспортировки по сети. Он также имеет преимущество, которое вам не нужно беспокоиться о байтовом порядке при загрузке/сохранении на диск/провод.
С учетом этих причин я бы пошел на std:: wstring внутри, или - если ваша библиотека GUI предлагает Widestring, используйте это (например, QString из QT). И для хранения дисков я бы написал небольшую платформу, независимую от оболочки для платформы api. Или я бы посмотрел unicode.org, если у них есть независимый от платформы код, доступный для этого преобразования.
для пояснения: корейские/японские буквы НЕ западные/латинские. Японцы выступают за кандзи. Вот почему я упомянул латинский набор символов.
для UTF-16 не 1 символ /2 байта. Это предположение верно только для символов, находящихся на базовой многоязычной плоскости (см. http://en.wikipedia.org/wiki/UTF16). Однако большинство пользователей UTF-16 предполагают, что все символы находятся на BMP. Если это не может быть гарантировано для вашего приложения, вы можете переключиться на UTF32 или переключиться на UTF8.
Все еще UTF-16 используется по причинам, упомянутым выше во многих API-интерфейсах (например, Windows, QT, Java,.NET, wxWidgets)