是(w)ifstream支持不同的编码

pet*_*hen 13 c++ unicode stl character-encoding wifstream

当我使用wifstream将文本文件读取为宽字符串(std :: wstring)时,流实现是否支持不同的编码 - 即它是否可以用于读取例如ASCII,UTF-8和UTF-16文件?

如果没有,我该怎么办?

(我需要阅读整个文件,如果这有所不同)

qua*_*ark 22

C++通过std::localefacet和facet 支持字符编码std::codecvt.一般的想法是,一个locale对象描述了系统的各个方面,这些方面可能因文化,人类语言而异.这些方面分解为facets,它们是定义如何构造依赖于本地化的对象(包括I/O流)的模板参数.当您读取istream或写入a时ostream,每个字符的实际写入将通过区域设置的方面进行过滤.这些方面不仅包括Unicode类型的编码,还包括如何编写大数字(例如逗号或句点),货币,时间,大写以及一系列其他细节等各种功能.

然而,仅仅因为存在编码的设施并不意味着标准库实际上处理所有编码,也不会使这样的代码变得简单.甚至像你应该阅读的字符大小这样的基本内容(更不用说编码部分)也很困难,因为wchar_t它可能太小(损坏你的数据),或者太大(浪费空间),以及最常见的编译器(例如Visual C++和Gnu C++)确实有不同的实现方式.因此,您通常需要找到外部库来进行实际编码.

  • iconv通常被认为是正确的,但很难找到如何将它绑定到C++机制的示例.
  • jla3ep提到了 libICU,这是非常彻底的,但C++ API并没有尝试很好地使用标准(据我所知:你可以扫描示例,看看你能做得更好.)

我能找到的涵盖所有基础的最直接的例子来自Boost的UTF-8 codecvt方面,其中一个例子专门尝试编码UTF-8(UCS4)以供IO流使用.它看起来像这样,虽然我不建议只是逐字复制它.需要更多的挖掘源于理解它(我并不声称):

typedef wchar_t ucs4_t;

std::locale old_locale;
std::locale utf8_locale(old_locale,new utf8_codecvt_facet<ucs4_t>);

...

std::wifstream input_file("data.utf8");
input_file.imbue(utf8_locale);
ucs4_t item = 0;
while (ifs >> item) { ... }
Run Code Online (Sandbox Code Playgroud)

要了解有关区域设置以及它们如何使用构面(包括codecvt)的更多信息,请查看以下内容: