代码之家  ›  专栏  ›  技术社区  ›  peterchen

ifstream是否支持不同的编码?

  •  12
  • peterchen  · 技术社区  · 16 年前

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

    如果没有,我该怎么办?

    (如果有区别的话,我需要阅读整个文件)

    3 回复  |  直到 16 年前
        1
  •  22
  •   Community CDub    8 年前

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

    然而,仅仅因为存在进行编码的工具并不意味着标准库实际上可以处理所有编码,也不意味着这样的代码很容易做对。即使是像你应该阅读的字符大小这样的基本内容(更不用说编码部分)也很困难,比如 wchar_t 可能太小(数据混乱),或者太大(浪费空间),以及最常见的编译器(例如VisualC++和GNU C++) 在实现的规模上存在差异。因此,通常需要找到外部库来进行实际的编码。

    我能找到的最简单的例子是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 )查看以下内容:

        2
  •  4
  •   Kirill V. Lyadvinsky    16 年前

    ifstream 不关心文件的编码。它只是从文件中读取字符(字节)。 wifstream 读取宽字节( wchar_t ,但它仍然不知道任何有关文件编码的信息。 Wifstream公司 对于UCS-2_固定长度的Unicode字符编码(每个字符用两个字节表示)来说已经足够好了。

    你可以用IBM ICU 用于处理Unicode文件的库。

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

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

        3
  •  1
  •   Max Lybbert    16 年前

    宽字符串和宽字符流的设计提前了utf-8、utf-16和unicode的日期。如果您想获得技术信息,标准字符串和标准流不一定在ASCII上操作(只是基本上所有的计算机都使用ASCII;您可能有一台EBCDIC机器)。

    陈瑞蒙一次 wrote a series illustrating how to work with different wide character stream/string types .