当我使用 wifstream 将文本文件读取为宽字符串 (std::wstring) 时,流实现是否支持不同的编码 - 即它可以用于读取例如ASCII、UTF-8 和 UTF-16 文件?
如果没有,我该怎么办?
(我需要阅读整个文件,如果这有影响的话)
C++ 通过以下方式支持字符编码std::locale
和侧面std::codecvt
。总体思路是locale
对象描述了系统的各个方面,这些方面可能因文化、(人类)语言而异。这几个方面又细分为facet
s,它们是定义如何构造本地化相关对象(包括 I/O 流)的模板参数。当你从一个istream
或写信给ostream
,每个字符的实际书写都会通过区域设置的方面进行过滤。这些方面不仅涵盖 Unicode 类型的编码,还涵盖各种特征,例如如何写入大数字(例如使用逗号或句点)、货币、时间、大小写以及大量其他细节。
然而,仅仅因为存在进行编码的工具并不意味着标准库实际上可以处理所有编码,也不意味着这样的代码可以简单地正确执行。即使是像你应该读入的字符大小这样的基本事情(更不用说编码部分)也是很困难的,因为wchar_t
可能太小(破坏数据),也可能太大(浪费空间),以及最常见的编译器(例如 Visual C++ 和 Gnu C++)do不同之处在于它们的实施规模有多大。所以你通常需要找到外部库来进行实际的编码。
-
iconv http://www.gnu.org/software/libiconv/人们普遍认为这是正确的,但是很难找到如何将其绑定到 C++ 机制的示例。
-
jla3ep 提到 https://stackoverflow.com/questions/1274910/does-wifstream-support-different-encodings/1274989#1274989 libICU http://site.icu-project.org,这是非常彻底的,但是C++ API http://icu-project.org/apiref/icu4c/并没有尝试很好地适应标准(据我所知:您可以扫描examples http://bugs.icu-project.org/trac/browser/icu/trunk/source/samples看看你是否可以做得更好。)
我能找到的涵盖所有基础的最简单的例子来自 BoostUTF-8 codecvt 方面 http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/codecvt.html,其中有一个专门尝试编码 UTF-8 (UCS4) 以供 IO 流使用的示例。它看起来像这样,但我不建议只是逐字复制它。需要更多的挖掘来源 https://svn.boost.org/trac/boost/browser/trunk/boost/detail/utf8_codecvt_facet.hpp理解它(我不声称):
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
),请看以下内容:
- 内森·迈尔斯有一个对语言环境和方面的全面解释 http://www.cantrip.org/locale.html。迈尔斯是区域设置概念的设计者之一。他有更正式的文档 http://www.cantrip.org/lib-locales.html如果你想涉足其中。
- Apache 的标准库实现(以前的 RogueWave 的)有一个完整的方面列表 http://stdcxx.apache.org/doc/stdlibug/24-2.html.
- 尼古拉·约苏蒂斯C++ 标准库 http://www.josuttis.com/libbook/第 14 章专门讨论这个主题。
- 安吉莉卡·兰格和克劳斯·克雷夫特标准 C++ IOStream 和区域设置 https://rads.stackoverflow.com/amzn/click/com/0201183951奉献了一整本书。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)