当我使用wifstream将文本文件读取为宽字符串(std :: wstring)时,流实现是否支持不同的编码 - 即它是否可用于读取例如ASCII,UTF-8和UTF-16文件?
如果没有,我该怎么做?
(我需要阅读整个文件,如果这有所不同)
答案 0 :(得分:22)
C ++通过std::locale
和方面std::codecvt
支持字符编码。一般的想法是,locale
对象描述了系统的各个方面,这些方面可能因文化,人类语言而异。这些方面被分解为facet
,它们是定义如何构造依赖于本地化的对象(包括I / O流)的模板参数。当您从istream
读取或写入ostream
时,每个字符的实际写入都会通过区域设置的方面进行过滤。这些方面不仅包括Unicode类型的编码,还包括诸如大写数字(例如逗号或句号),货币,时间,大写以及大量其他细节等各种功能。
然而,仅仅因为存在编码的设施并不意味着标准库实际上处理所有编码,也不会使这样的代码变得简单。即使像你应该阅读的字符大小这样的基本内容(更不用说编码部分)也很困难,因为wchar_t
可能太小(破坏你的数据),或者太大(浪费空间),以及最常见的编译器(例如Visual C ++和Gnu C ++) do 在实现的程度上有所不同。因此,您通常需要找到外部库来进行实际编码。
我能找到的涵盖所有基础的最直接的例子来自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。