Транскодирование символов на лету с использованием iostreams и ICU
Я хотел бы перекодировать кодировку символов на лету. Я хотел бы использовать iostreams и мое собственное транскодирование streambuf
Например:
xcoder_streambuf xbuf( "UTF-8", "ISO-8859-1", cout.rdbuf() );
cout.rdbuf( &xbuf );
char *utf8_s; // pointer to buffer containing UTF-8 encoded characters
// ...
cout << utf8_s; // characters are written in ISO-8859-1
Реализация xcoder_streambuf
будет использовать API конвертеров ICU. Это будет принимать данные, поступающие (в этом случае от utf8_s
), перекодируйте его и запишите, используя оригинал iostream steambuf
,
Это разумный путь? Если нет, то что будет лучше?
1 ответ
Это разумный путь?
Да, но это не то, что от вас ожидают в современном (как в 1997 году) iostream.
Поведение вывода через basic_streambuf<>
определяется overflow(int_type c)
виртуальная функция.
Описание basic_filebuf<>::overflow(int_type c = traits::eof())
включает в себя a_codecvt.out(state, b, p, end, xbuf, xbuf+XSIZE, xbuf_end);
где a_codecvt
определяется как:
const codecvt<charT,char,typename traits::state_type>& a_codecvt
= use_facet<codecvt<charT,char,typename traits::state_type> >(getloc());
так что вы должны imbue
locale
с соответствующими codecvt<charT,char,typename traits::state_type>
конвертер.
Класс
codecvt<internT,externT,stateT>
предназначен для использования при преобразовании одной кодировки символов в другую, например, из широких символов в многобайтовые символы или между кодировками широких символов, такими как Unicode и EUC.
Поддержка стандартной библиотеки Unicode достигла определенного прогресса с 1997 года:
код специализации конвертирует между схемами кодирования UTF-32 и UTF-8.
Это, кажется, то, что вы хотите (коды ISO-8859-1 - это коды USC-4 = UTF-32).
Если нет, то что будет лучше?
Я бы представил другой тип для UTF8, например:
struct utf8 { символ без знака d; // d для данных }; struct latin1 { беззнаковый символ c; // c для персонажа };
Таким образом, вы не можете случайно пройти UTF8 там, где ожидается ISO-8859-*. Но тогда вам придется написать некоторый код интерфейса, и тип ваших потоков не будет istream
/ ostream
,
Отказ от ответственности: я никогда не делал ничего подобного, поэтому я не знаю, возможно ли это на практике.