首页 > 解决方案 > 使用 utf-8 在 msvc 和 g++ 上的 std::fstream 不同行为

问题描述

std::string path("path.txt");
std::fstream f(path);
f.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
std::string lcpath;
f >> lcpath;

从 Windows 上读取 utf-8 文本path.txt失败,Windows 上的 MSVC 编译器lcpath无法将路径理解为 utf-8。

以下代码在使用 g++ 编译时在 linux 上正常工作。

    std::string path("path.txt");
    std::fstream ff;
    ff.open(path.c_str());
    std::string lcpath;
    ff>>lcpath;

在 windows(MSVC) 上是否fstream默认只假设 ascii?

在第一个片段中,如果我更改stringwithwstringfstreamwith wfstreamlcpath也会在 windows 上获得正确的值。

lcpath编辑:如果我使用转换读取MultiByteToWideChar(),我得到正确的表示。但是为什么我不能std::string在 Windows 上直接读取一个 UTF-8 字符串呢?

标签: c++encodingfstream

解决方案


灌输打开的文件可能很麻烦:

http://www.cplusplus.com/reference/fstream/filebuf/imbue/

如果 loc 与文件流缓冲区当前使用的语言环境不同,则内部位置指针指向文件的开头,或者其编码与状态无关。否则,它会导致未定义的行为。

这里的问题是,当打开一个文件并且文件中有一个 BOM 标记时,这通常会由当前安装的本地文件从文件中读取。因此,position pointer不再是文件的开头,我们有未定义的行为。

为了确保您的本地设置正确,您必须在打开文件之前执行此操作。

std::fstream f;
f.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));

std::string path("path.txt");
f.open(path);

std::string lcpath;
f >> lcpath;

推荐阅读