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




