2009-05-07 3 views
6

Мне известно о ICU и небольших библиотеках, таких как utf8 one в проекте кода (забудьте точное имя), однако ни один из них не является именно тем, что я хочу.C++ вопросы юникода

То, что я действительно хочу, это что-то вроде ОИТ, но обернуто более дружелюбно.

В частности:

  • Полностью объектно-ориентированное
  • реализациях C++ стандарт потоков или, по крайней мере что-то, что выполняет ту же роль.
  • Может форматировать время, даты и т. Д. В зависимости от локали (например, dd/mm/yy в Великобритании и mm/dd/yy в США).
  • Позволяет мне выбрать «внутреннюю» кодировку строк, поэтому я могу, например, использовать UTF-16 для окон, чтобы избежать большого количества преобразований при передаче строк в и из окон API и DirectX
  • Простое преобразование строк между кодировками

Если такая библиотека не существует, можно обернуть ICU вверх, используя стандарт C++ классы, так что я могу, например, создать ustring, который имеет идентичное использование в StD :: строку и зЬй :: wstring , а также реализовать версии потоков (оптимально, если они полностью совместимы с существующими, то есть я мог бы передать его функции, ожидающей std :: ostream, и будет выполнять преобразование между ее внутренним форматом и d ascii (или utf-8) на лету)? Предполагая, насколько это возможно?

EDIT: Также, взглянув на стандарт C++ 0x и замеченные литералы для utf8, utf16 и utf32, означает ли это, что стандартная библиотека (например, строки, потоки и т. Д.) Полностью поддерживает эти кодировки и преобразование между их? Если да, то кто-нибудь понял, как долго это будет, пока Visual Studio не поддержит эти функции?

EDIT2: Что касается использования существующей поддержки C++, я буду искать язык и фасет.

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

привело к следующему гекса в файле
48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A
, который явно ASCII, а не ожидаемой UTF-16 выход:
FF FE 48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00 6F 00 72 00 6C 00 64 00 0D 00 0A 00

+0

Текст UTF-16 фактически ** преобразован ** в локальную кодировку 8 бит! Таким образом, вы не записываете utf-16 в файл. Не забудьте вызвать std :: locale :: global (std :: locale()); – Artyom

+0

Итак, как я могу сказать, какой кодировкой я хочу получить файл? Я попробовал std :: local ... вы упомянули выше, но он, похоже, не имеет никакого эффекта :( –

+0

Хорошо, например, если система locale 'ru_RU.UTF-8', то кодировка является utf-8, если она ru_RU.KOI-8, то это KOI. Вы также можете указать другой язык: 'locale :: globale (locale (« de_DE.ISO-8859-1 »));» (примечание: я использую имена локалей имен POSIX, для Windows вы должны проверить, что имена локалей: – Artyom

ответ

1

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

Также посмотрев на C++ 0x стандарт и заметил литералов для utf8, utf16 и UTF32, что значит, что стандартная библиотека (например, строки, потоки, и т.д.) будет полностью поддерживать эти encodeings и преобразование между ними ?

Да. Но обратите внимание, что это разные типы данных, а не ваша очередная последовательность wchar или wstring.

Если да, то кто-нибудь понял, как долго это будет, пока Visual Studio не поддержит эти функции?

Насколько мне известно, vc9 (VS2008) имеет частичную поддержку некоторых функций TR1. Ожидается, что vc10 (VS2010) получит лучшую поддержку.

+0

Да, но он не форматирует его до определенного кодирования, конечно, я мог бы отформатировать его до строки ascii, а затем закодировать его, но что, если бы я хотел использовать длинные имена в chinease, что невозможно в ascii? –

+0

Вот где кодирующая часть Язык поиска: – dirkgently

+0

Да. В большинстве случаев используется локальное функционирование nality. Не применяйте формат для своего пользователя. Пусть система решит формат, который вам нужно сделать, чтобы убедиться, что языковой стандарт установлен правильно, тогда поток будет работать правильно. (+1) –

3

То, что я действительно хочу это нечто вроде СИС, но завернутые в более дружественной манере

несчастливо, нет такой вещи. Их API не так страшен, поэтому вы можете привыкнуть к нему для некоторых усилий.

Может форматировать время, даты и т. Д. В зависимости от локали (например, dd/mm/yy в Великобритании и mm/dd/yy в США).

Существует полная поддержка его в классе std::locale, о том, как его использовать. Вы также можете указать локаль для std::iostream, чтобы она правильно форматировала числа, даты.

Простого преобразование строк между кодировками

std::locale обеспечивает грань для coverting 8bits локальной кодировки широких одной и обратно.

так что я могу, например, сделать его использовать UTF-16

ICU использует UTF-16 внутри, win32 wchar_t и использовать wstring UTF-16, а также, в соответствии с другими операционными системами большинство реализаций дают wchar_t, как utf-32 и wstring использует utf-32.

Примечания: Поддержка std::locale не является совершенной, но она уже дает множество инструментов, которые полезны для манипуляций с charrecter.

См: http://www.cplusplus.com/reference/std/locale/

-1

Я сделал свою собственную небольшую обертку. Я могу поделиться, если вы хотите.

+0

Поддерживает ли он потоки C++, потому что моя основная проблема с ICU и факт, что у меня очень большое приложение, я хочу работать с unicode. –

+0

Да, использует boost :: фильтры iostreams – piotr

-1

Жесткая удача. Я знаю, что библиотеки Dinkumware предлагают некоторую поддержку Unicode - вы можете посмотреть документацию на своем веб-сайте. AFAIK, это не бесплатно.

2

Это, как я использую ICU для преобразования между станд :: строки (в кодировке UTF-8) и Std :: wstring

/** Converts a std::wstring into a std::string with UTF-8 encoding. 
*/ 
template < typename StringT > 
StringT utf8 (std::wstring const & rc_string); 

/** Converts a std::String with UTF-8 encoding into a std::wstring. 
*/ 
template < typename StringT > 
StringT utf8 (std::string const & rc_string); 

/** Nop specialization for std::string. 
*/ 
template < > 
inline std::string utf8 (std::string const & rc_string) 
{ 
    return rc_string; 
} 

/** Nop specialization for std::wstring. 
*/ 
template < > 
inline std::wstring utf8 (std::wstring const & rc_string) 
{ 
    return rc_string; 
} 

template < > 
std::string utf8 (std::wstring const & rc_string) 
{ 
    std::string result; 
    if(rc_string.empty()) 
    return result; 

    std::vector<UChar> buffer; 

    result.resize(rc_string.size() * 3); // UTF-8 uses max 3 bytes per char 
    buffer.resize(rc_string.size() * 2); // UTF-16 uses max 2 bytes per char 

    UErrorCode status = U_ZERO_ERROR; 
    int32_t len = 0; 

    u_strFromWCS(
    &buffer[0], 
    buffer.size(), 
    &len, 
    &rc_string[0], 
    rc_string.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strFromWCS failed"); 
    } 
    buffer.resize(len); 

    u_strToUTF8(
    &result[0], 
    result.size(), 
    &len, 
    &buffer[0], 
    buffer.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strToUTF8 failed"); 
    } 
    result.resize(len); 

    return result; 
}/* end of utf8 () */ 


template < > 
std::wstring utf8 (std::string const & rc_string) 
{ 
    std::wstring result; 
    if(rc_string.empty()) 
    return result; 

    std::vector<UChar> buffer; 

    result.resize(rc_string.size()); 
    buffer.resize(rc_string.size()); 

    UErrorCode status = U_ZERO_ERROR; 
    int32_t len = 0; 

    u_strFromUTF8(
    &buffer[0], 
    buffer.size(), 
    &len, 
    &rc_string[0], 
    rc_string.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strFromUTF8 failed"); 
    } 
    buffer.resize(len); 

    u_strToWCS(
    &result[0], 
    result.size(), 
    &len, 
    &buffer[0], 
    buffer.size(), 
    &status 
); 
    if(!U_SUCCESS(status)) 
    { 
    throw XXXException("utf8: u_strToWCS failed"); 
    } 
    result.resize(len); 

    return result; 
}/* end of utf8 () */ 

Используя это так просто:

std::string s = utf8<std::string>(std::wstring(L"some string")); 
std::wstring s = utf8<std::wstring>(std::string("some string")); 
+0

Одна ошибка: UTF-8 использует max * 4 * байт на символ. Одно неправильное использование термина: UTF-16 использует максимальные 2 * кодовые единицы * для каждого символа. – dalle

1

Я всегда работает таким образом:

байт потока в некоторой кодировке -> -> wistream -> СТЛ & подталкивание -> wostream -> -> байты потока в некоторых кодирование

Смежные вопросы