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

时间:2009-08-13 22:14:22

标签: c++ unicode stl character-encoding wifstream

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

如果没有,我该怎么做?

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

3 个答案:

答案 0 :(得分:22)

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

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

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

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

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) { ... }

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

答案 1 :(得分:4)

ifstream不关心文件的编码。它只是从文件中读取字符(字节)。 wifstream读取宽字节(wchar_t),但它仍然不知道有关文件编码的任何信息。 wifstream足以支持UCS-2 - Unicode的固定长度字符编码(每个字符用两个字节表示)。

您可以使用IBM ICU库来处理Unicode文件。

  

Unicode的国际组件(ICU)是一套成熟,可移植的C / C ++和Java库,用于Unicode支持,软件国际化(I18N)和全球化(G11N),在所有平台上为应用程序提供相同的结果。

     

ICU是根据非限制性开源许可证发布的,适用于商业软件和其他开源软件或免费软件。

答案 2 :(得分:1)

宽字符串和宽字符流的设计早于UTF-8,UTF-16和Unicode。如果你想获得技术,标准字符串和标准流不一定在ASCII上运行(基本上所有的计算机都使用ASCII;你可能有一台EBCDIC机器。)

Raymond Chen曾wrote a series illustrating how to work with different wide character stream/string types

相关问题