使用CLion+MinGW时UTF-8编码写入西里尔文字符至文件异常
解决MinGW环境下UTF-8文件写入与控制台输出冲突问题
问题根源
MinGW的标准文件流(fstream)默认采用系统本地编码(Windows下通常为GBK或windows-1251),当尝试写入UTF-8编码的西里尔文字符时,编码不匹配会导致文件中仅写入\0;而改用windows-1251编码写入文件时,虽然文件内容正常,但控制台已设置为UTF-8,输出时会把windows-1251编码的字符错误解析为UTF-8,出现Привет这类乱码。
解决方案一:为文件流显式指定UTF-8编码
利用MinGW兼容的MSVC函数_setmode,强制文件流以UTF-8模式读写:
#include <iostream> #include <fstream> #include <windows.h> #include <fcntl.h> #include <io.h> using namespace std; int main() { // 配置控制台为UTF-8编码 system("CHCP 65001 > nul"); SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); fstream fileStream; fileStream.open("file.txt", ios_base::in | ios_base::out | ios_base::app); // 将文件流设置为UTF-8文本模式 if (fileStream.is_open()) { _setmode(_fileno(fileStream.rdbuf()->file()), _O_U8TEXT); } string message; cin >> message; fileStream << message << endl; fileStream.close(); }
解决方案二:使用宽字符流处理Unicode
改用宽字符类型(wstring、wfstream)配合UTF-8 locale,统一处理控制台与文件的编码:
#include <iostream> #include <fstream> #include <windows.h> #include <locale> using namespace std; int main() { // 配置控制台为UTF-8编码 system("CHCP 65001 > nul"); SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); // 创建UTF-8 locale对象 locale utf8_locale(locale(), new codecvt_utf8<wchar_t>()); wfstream fileStream; fileStream.open(L"file.txt", ios_base::in | ios_base::out | ios_base::app); if (fileStream.is_open()) { // 为文件流注入UTF-8 locale fileStream.imbue(utf8_locale); } wstring message; wcin >> message; fileStream << message << endl; // 控制台输出宽字符也正常 wcout << L"Привет" << endl; fileStream.close(); }
说明
- 方案一适合习惯使用窄字符串的场景,直接修改文件流的编码模式即可;
- 方案二更贴合Unicode原生处理,避免编码转换的潜在问题,同时控制台输出宽字符也不会出现乱码;
- 两种方案都能保证:控制台输入输出UTF-8正常,文件写入的西里尔文字符也是正确的UTF-8编码。
内容的提问来源于stack exchange,提问作者man
相关产品推荐
相关产品推荐

