0

我想codecvt使用 ICU 实现一个方面,以便在内部从任何字符编码(ICU 支持)转换为 UTF-8。我知道它codecvt_byname存在并且它可以用来做我想要的一部分,如本例所示。该示例的问题在于它(1)使用宽字符流(我想使用“常规”、面向字节的流)和(2)需要 2 个流来执行转换。相反,我想要一个像这样的流:

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

因此,我想做这样的实现,使用 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,即,我如何知道何时到达输入的末尾。

一点帮助?

4

1 回答 1

0

codecvt facet并不打算在不同的编码之间进行转换。相反,它将一个字符可能使用多个外部单词(通常是字节)编码的外部编码转换为每个字符仅由一个单词表示的内部表示(例如 char、wchar_t、char16_t 等)。

从这个角度来看,“结束”一个内部字符序列是没有意义的。如果没有更多可用的外部字,则转换完成,如果最后一个字符仍然不完整,则这是传输错误。因此,不需要指示转换完成,相应地,没有接口。这应该澄清“冲洗”论点确实应该始终是“错误的”。

我意识到 UTF-8 并不完全符合让一个单词代表一个字符的要求。但是,这将困扰您使用标准类型处理字符串的 UTF-8 处理。不过,只要您避免修改注射器,事情通常就可以正常工作。

“reset”参数可能是为了处理流中的搜索。我认为 filebuf 应该在寻找时提供一个新的 state_type 对象。这可能表明 ICU 内部需要重置。但是,我不知道ICU接口。因此,我也不知道您是否要提供数据透视缓冲区。

于 2011-12-30T17:40:22.607 回答