使用iostream和ICU即时转码字符

时间:2011-12-10 01:04:39

标签: c++ unicode character-encoding iostream icu

我希望即时转码字符编码。我想使用iostream和我自己的转码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的实施将使用ICU的转换器API。这将使数据进入(在这种情况下,来自utf8_s),对其进行转码,并使用iostream的原始steambuf将其写出来。

这是一种合理的方式吗?如果不是,那会更好一点?

1 个答案:

答案 0 :(得分:0)

  

这是一种合理的方式吗?

是的,但这不是你在现代(如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)之间。

自1997年以来,对Unicode的标准库支持取得了一些进展:

  

专门化codecvt在UTF-32和UTF-8编码方案之间进行转换。

这似乎是你想要的(ISO-8859-1代码是USC-4代码= UTF-32)。

  

如果没有,会有什么更好的?

我会为UTF8引入一种不同的类型,例如:

struct utf8 {
    unsigned char d; // d for data
};

struct latin1 {
    unsigned char c; // c for character 
};

这样你就不会意外地传递需要ISO-8859- *的UTF8。但是,您必须编写一些接口代码,并且您的流类型不会是istream / ostream

免责声明:我从未真正做过这样的事情,所以我不知道它在实践中是否可行。