c++ - (w)ifstream 是否支持不同的编码

标签 c++ unicode stl character-encoding wifstream

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

如果没有,我该怎么办?

(如果有影响,我需要阅读整个文件)

最佳答案

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

然而,仅仅因为存在进行编码的工具并不意味着标准库实际上可以处理所有编码,也不意味着这些代码可以简单地正确执行。即使是你应该读入的字符大小(更不用说编码部分)这样基本的东西也很困难,因为 wchar_t 可能太小(破坏你的数据)或太大(浪费空间) ,而最常见的编译器(例如 Visual C++ 和 Gnu C++)确实在其实现的大小上有所不同。所以一般需要找外部库来做实际的编码。

  • iconv一般认为是正确的,但很难找到如何将其绑定(bind)到 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),请查看以下内容:

关于c++ - (w)ifstream 是否支持不同的编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1274910/

相关文章:

c++ - 在编码时在类中声明一个非静态常量数据成员是否合适?

c++ - 跳出 try block 是否合法?

javascript - 将 HTML 实体(例如 – 或 – )与模板文字一起使用

Windows CE OpenCV 性能

c++ - 修改列表列表

c++ - 我在这里的绑定(bind)功能做错了什么?

C++ 如何将整数和长整型转换为 char 数组

python - 检查 stdout 是否支持 unicode?

android - 在 Android 中使用 iText 生成的 PDF 中不显示西里尔字母

c++ - 命名空间中的 gcc 编译时错误排序 vector