2011-12-30 56 views
0

我想实现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编码。

我的问题是:

  1. 我应该指定nullptr为“支点”为上述缓冲液,或提供自己的?
  2. 我不确定何时,如果有的话,我应该将reset参数(现在是第一个false以上)设置为true
  3. 我不知道如何知道何时将flush参数(当前是第二个false)设置为true,即我如何知道何时已达到输入的结尾。

有一点帮助吗?

+0

您应该在打开文件之前灌注()您的文件流。如果文件已经打开,很多系统会默默地忽略imbue()(这是因为关于对话的状态可能已经丢失)。 – 2011-12-30 15:54:15

+0

完成。其余的答案? – 2011-12-30 16:01:59

回答

0

该codecvt方面是而不是打算在不同的编码之间进行转换。相反,它从外部编码转换而来,其中一个字符可能使用多个外部字(通常是字节)编码为内部表示,其中每个字符只由一个字表示(例如char,wchar_t,char16_t等)。

从这个角度来看,“结束”内部字符序列是没有意义的。如果没有可用的外部单词,则转换完成,如果最后一个字符保持不完整,则这是传输过程中的错误。因此,不需要指出转换完成,并且相应地没有接口。这应该澄清,“同花大顺”的论点的确应该永远是“虚假的”。

我意识到UTF-8不太适合用单词表示一个字符的帐单。但是,这会困扰你使用标准类型处理字符串来处理UTF-8处理。但是,只要你保持清醒的修改,通常情况下工作就OK了。

“重置”参数可能旨在处理在流内搜索。我认为filebuf应该在寻求时提供一个新的state_type对象。这可能意味着ICU内部机构想要重置。但是,我不知道ICU接口。因此,我也不知道你是否想提供一个数据透视缓冲区。

+0

我最初的想法是有一个转码流缓冲区,但这家伙http://stackoverflow.com/a/8453807/99089说使用codecvt - 谁是对的?或者,如何以“优雅”的方式使用iostreams实现从任意编码到UTF-8的自动转换? – 2011-12-30 18:09:47

+0

'char16_t'和'wchar_t' *不*保证为每个字符一个字。 'char16_t'专门用于具有代理对的UTF-16代码单元。所以不,这不是每个“字符”的一个16位字。 – 2011-12-30 19:27:35

+0

@Nicol Bolas:实际上wchar_t的意图是每个字符一个单词(但Unicode委员会放弃了他们的既定目标,即在Java和Windows决定使用16位wchar_t后立即为所有字符创建一个16位编码)。你在概念上对char16_t是正确的,但是流和字符串类仍然假定一个字是一个字符。这是例如反映在codecvt界面中。 – 2011-12-30 19:51:47