You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C++中如何让文件流以UTF-8编码读取文本?

解决Windows下wifstream/wofstream读写UTF-8文件乱码的问题

嘿,我懂你现在的处境——已经靠_setmode搞定了控制台stdin/stdout的UTF-8读写(用wcin/wcout完全正常),但换成文件流就乱码,确实头疼!下面给你两种可行的解决方案,分别适配Windows特有的快速方法和跨平台的标准方法:

方法一:复用_setmode(Windows专属)

和你处理控制台流的思路一致,我们可以给文件流对应的文件描述符设置UTF-8模式。核心是通过_fileno获取文件流的底层文件描述符,再用_setmode切换到_O_U8TEXT模式。

示例代码:

#include <fstream>
#include <fcntl.h>   // 包含_O_U8TEXT定义
#include <io.h>      // 包含_fileno和_setmode
#include <iostream>

int main() {
    // 读取UTF-8文件
    std::wifstream in_file("utf8_input.txt");
    if (in_file.is_open()) {
        // 将文件流设置为UTF-8文本模式
        _setmode(_fileno(in_file), _O_U8TEXT);
        
        std::wstring content;
        std::getline(in_file, content);
        std::wcout << L"读取内容:" << content << std::endl;
        in_file.close();
    }

    // 写入UTF-8文件
    std::wofstream out_file("utf8_output.txt");
    if (out_file.is_open()) {
        _setmode(_fileno(out_file), _O_U8TEXT);
        
        out_file << L"测试UTF-8中文写入:你好,世界!" << std::endl;
        out_file.close();
    }

    return 0;
}

注意:这个方法依赖MSVC的扩展API,只能在Windows平台使用,而且不要给文件流加上ios::binary模式,否则会破坏UTF-8的编码转换逻辑。

方法二:使用标准库codecvt_utf8(跨平台)

如果你需要跨平台兼容性,推荐用C++标准库的std::codecvt_utf8来指定编码转换规则,通过imbue方法给文件流绑定对应的locale。

示例代码:

#include <fstream>
#include <locale>
#include <iostream>

int main() {
    // 创建支持UTF-8转换的locale
    std::locale utf8_locale(std::locale(), new std::codecvt_utf8<wchar_t>);

    // 读取UTF-8文件
    std::wifstream in_file("utf8_input.txt");
    in_file.imbue(utf8_locale);  // 给输入流绑定UTF-8 locale
    
    std::wstring line;
    while (std::getline(in_file, line)) {
        std::wcout << L"读取行:" << line << std::endl;
    }

    // 写入UTF-8文件
    std::wofstream out_file("utf8_output.txt");
    out_file.imbue(utf8_locale);  // 给输出流绑定UTF-8 locale
    
    out_file << L"跨平台UTF-8测试:Hello, 世界!" << std::endl;

    return 0;
}

说明:这个方法基于C11及以后的标准,大部分主流编译器(MSVC、GCC、Clang)都支持。需要注意的是,有些环境可能需要显式启用C11或更高版本的编译选项。

两种方法都能解决你遇到的乱码问题,根据你的平台需求选就行啦!

内容的提问来源于stack exchange,提问作者Joshua Segal

火山引擎 最新活动