【问题标题】:Using ICU to implement my own codecvt facet使用 ICU 实现我自己的 codecvt facet
【发布时间】:2012-01-30 15:31:53
【问题描述】:

我想使用 ICU 实现codecvt facet,以便在内部从任何字符编码(ICU 支持)转换为 UTF-8。我知道codecvt_byname 存在,它可以用来做我想做的部分事情,如this example 所示。该示例的问题在于它(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

因此,我想做一个像 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. 我应该像上面那样为“pivot”缓冲区指定nullptr,还是提供我自己的?
  2. 我不确定何时应该将reset 参数(目前是上面的第一个false)设置为true
  3. 不清楚我如何知道何时将flush 参数(目前是上面的第二个false)设置为true,即,我如何知道何时到达输入的末尾。

有点帮助?​​

【问题讨论】:

  • 您应该在打开文件之前灌输()您的文件流。如果文件已经打开,许多系统会默默地忽略 imbue()(这是因为有关对话的状态可能已经丢失)。
  • 完成。剩下的有什么答案吗?

标签: c++ iostream icu codecvt


【解决方案1】:

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

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

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

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

【讨论】:

  • 我最初的想法是有一个转码流缓冲区,但这个人stackoverflow.com/a/8453807/99089 说要使用编解码器——那么谁是对的?或者,您将如何使用 iostreams 以“优雅”的方式实现从任意编码到 UTF-8 的自动转换?
  • char16_twchar_t保证每个字符一个单词。 char16_t 专门用于具有代理对的 UTF-16 代码单元。所以不,每个“字符”不是一个 16 位字。
  • @Nicol Bolas:实际上 wchar_t 的目的是每个字符一个字(但 Unicode 委员会在 Java 和 Windows 决定使用 16 位后不久就放弃了为所有字符创建 16 位编码的既定目标对于 wchar_t)。 char16_t 在概念上是正确的,但流和字符串类仍然假设一个单词是一个字符。这是例如反映在codecvt界面中。
  • @DietmarKühl:我认为这我想要做的。只是我的“内部表示”恰好是UTF-8。
  • @DietmarKühl:那么规定的方式来做我想做的事?
猜你喜欢
  • 1970-01-01
  • 2015-10-05
  • 2011-02-28
  • 1970-01-01
  • 2017-07-27
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多