使用ICU实现我自己的编码方面
我想实现codecvt
方面使用ICU从任何字符编码(ICU支持)转换为UTF-8内部。我知道codecvt_byname
存在,它可以用来做我想要的一部分,如this example所示。这个例子的问题是它(1)使用宽字符流(我想使用“常规”,面向字节的流)和(2)需要2个流来执行转换。相反,我要像一个单一的数据流:使用ICU实现我自己的编码方面
locale loc(locale(), new icu_codecvt("ISO-8859-1"));
ifstream ifs;
ifs.imbue(loc);
ifs.open("/path/to/some/file.txt");
// data read from ifs here will have been converted from ISO-8859-1 to UTF-8
因此,我的魔杖做一个类似的实现,但this使用ICU而不是iconv
。 鉴于此,我的实现的do_in()
是:
icu_codecvt::result icu_codecvt::do_in(state_type &state,
extern_type const *from, extern_type const *from_end,
extern_type const *&from_next, intern_type *to,
intern_type *to_end, intern_type *&to_next) const {
from_next = from;
to_next = to;
if (always_noconv_)
return noconv;
our_state *const s = state_store_.get(state);
UErrorCode err = U_ZERO_ERROR;
ucnv_convertEx(
s->utf8_conv_, s->extern_conv_, &to_next, to_end, &from_next, from_end,
nullptr, nullptr, nullptr, nullptr, false, false, &err
);
if (err == U_TRUNCATED_CHAR_FOUND)
return partial;
return U_SUCCESS(err) ? ok : error;
}
的our_state
对象维护两个UConverter*
指针,一个用于“外部”编码(在本例中,ISO-8859-1)和一个用于UTF-8编码。
我的问题是:
- 我应该指定
nullptr
为“支点”为上述缓冲液,或提供自己的? - 我不确定何时,如果有的话,我应该将
reset
参数(现在是第一个false
以上)设置为true
。 - 我不知道如何知道何时将
flush
参数(当前是第二个false
)设置为true
,即我如何知道何时已达到输入的结尾。
有一点帮助吗?
该codecvt方面是而不是打算在不同的编码之间进行转换。相反,它从外部编码转换而来,其中一个字符可能使用多个外部字(通常是字节)编码为内部表示,其中每个字符只由一个字表示(例如char,wchar_t,char16_t等)。
从这个角度来看,“结束”内部字符序列是没有意义的。如果没有可用的外部单词,则转换完成,如果最后一个字符保持不完整,则这是传输过程中的错误。因此,不需要指出转换完成,并且相应地没有接口。这应该澄清,“同花大顺”的论点的确应该永远是“虚假的”。
我意识到UTF-8不太适合用单词表示一个字符的帐单。但是,这会困扰你使用标准类型处理字符串来处理UTF-8处理。但是,只要你保持清醒的修改,通常情况下工作就OK了。
“重置”参数可能旨在处理在流内搜索。我认为filebuf应该在寻求时提供一个新的state_type对象。这可能意味着ICU内部机构想要重置。但是,我不知道ICU接口。因此,我也不知道你是否想提供一个数据透视缓冲区。
我最初的想法是有一个转码流缓冲区,但这家伙http://*.com/a/8453807/99089说使用codecvt - 谁是对的?或者,如何以“优雅”的方式使用iostreams实现从任意编码到UTF-8的自动转换? – 2011-12-30 18:09:47
'char16_t'和'wchar_t' *不*保证为每个字符一个字。 'char16_t'专门用于具有代理对的UTF-16代码单元。所以不,这不是每个“字符”的一个16位字。 – 2011-12-30 19:27:35
@Nicol Bolas:实际上wchar_t的意图是每个字符一个单词(但Unicode委员会放弃了他们的既定目标,即在Java和Windows决定使用16位wchar_t后立即为所有字符创建一个16位编码)。你在概念上对char16_t是正确的,但是流和字符串类仍然假定一个字是一个字符。这是例如反映在codecvt界面中。 – 2011-12-30 19:51:47
您应该在打开文件之前灌注()您的文件流。如果文件已经打开,很多系统会默默地忽略imbue()(这是因为关于对话的状态可能已经丢失)。 – 2011-12-30 15:54:15
完成。其余的答案? – 2011-12-30 16:01:59