C++ Unicode вопросы
Я знаю об ICU и небольших библиотеках, таких как utf8, одна на проекте кода (забудьте точное имя), однако ни одна из них не является именно тем, что я хочу.
Что я действительно хочу, так это что-то вроде ICU, но в более дружеской манере.
В частности:
- Полностью объектно-ориентированный
- Реализации стандартных потоков C++ или хотя бы что-то, выполняющее ту же роль.
- Можно форматировать время, даты и т. Д. В зависимости от локали (например, дд / мм / гг в Великобритании и мм / дд / гг в США).
- Позволяет мне выбрать "внутреннюю" кодировку строк, поэтому я могу, например, заставить ее использовать UTF-16 на окнах, чтобы избежать большого количества преобразований при передаче строк в и из Windows API и DirectX
- Простое преобразование строк между кодировками
Если такой библиотеки не существует, возможно ли обернуть ICU, используя стандартные классы C++, так что я могу, например, создать ustring, которая будет использовать идентично std::string и std::wstring, а также реализовать версии потоков (оптимально, чтобы они были полностью совместимы с существующими, то есть я мог бы передать это функции, ожидающей std::ostream, и она выполнит преобразование между своим внутренним форматом и ascii (или utf-8) на лету)? Предполагая, что это возможно, сколько работы это будет?
РЕДАКТИРОВАТЬ: Кроме того, глядя на стандарт C++0x и заметил литералы для utf8, utf16 и utf32, означает ли это, что стандартная библиотека (например, строки, потоки и т. Д.) Будет полностью поддерживать эти кодировки и преобразование между ними? Если так, то кто-нибудь понял, как скоро Visual Studio будет поддерживать эти функции?
РЕДАКТИРОВАТЬ 2: Что касается использования существующей поддержки C++, я буду искать локаль и аспекты.
Одна из проблем, с которыми я столкнулся, состоит в том, что при использовании потоков, определенных вокруг wchar_t, который составляет 2 байта под окнами для файлового ввода-вывода, все же кажется, что он все еще использует ascii для файлов, которые они сами.
std::wofstream file(L"myfile.txt", std::ios::out);
file << L"Hello World!" << std::endl;
привел к следующему hex в файле
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
6 ответов
Что я действительно хочу, так это что-то вроде ICU, но в более дружеской манере
К сожалению, такого нет. Их API не ТАК ужасен, так что вы можете привыкнуть к нему с некоторыми усилиями.
Можно форматировать время, даты и т. Д. В зависимости от локали (например, дд / мм / гг в Великобритании и мм / дд / гг в США).
Существует полная поддержка этого в std::locale
класс, читайте о том, как его использовать. Вы также можете указать локаль для std::iostream
так что это будет форматировать числа, даты правильно.
Простое преобразование строк между кодировками
std::locale
обеспечивает аспекты для покрытия 8-битного локального кодирования для широкого и обратно.
так что я могу, например, заставить его использовать UTF-16
ICU использует utf-16 внутри, win32 wchar_t
и wstring также использует utf-16, в других ОС большинство реализаций дают wchar_t как utf-32, а wstring использует utf-32.
Примечания: Поддержка std::locale
не идеален, но он уже дает много инструментов, которые полезны для манипуляций charrecter.
Вот как я использую ICU для преобразования между std::string (в 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"));
Я всегда работаю таким образом:
поток байтов в некоторой кодировке -> ICU
-> wistream -> stl & boost -> wostream -> ICU
-> поток байтов в некоторой кодировке
Форматирование даты, времени и т. Д. Может быть выполнено путем указания конкретной локали. Что касается прокрутки собственного - это всегда возможно, беря столько или меньше из базовой библиотеки, сколько вам нужно.
Также, посмотрев на стандарт C++0x и заметив литералы для utf8, utf16 и utf32, означает ли это, что стандартная библиотека (например, строки, потоки и т. Д.) Будет полностью поддерживать эти кодировки и преобразование между ними?
Да. Но обратите внимание, что это разные типы данных, а не ваши обычные wchar
последовательность или wstring
,
Если так, то кто-нибудь понял, как скоро Visual Studio будет поддерживать эти функции?
Насколько я знаю: vc9 (VS2008) имеет только частичную поддержку некоторых функций TR1. Ожидается, что vc10 (VS2010) получит лучшую поддержку.
Я сделал свою собственную маленькую обертку. Я могу поделиться, если хотите.
Вот незадача. Я знаю, что библиотеки Dinkumware предлагают некоторую поддержку Unicode - вы можете посмотреть документацию на их веб-сайте. AFAIK, это не бесплатно.