Windows 控制台以 UTF-8 编码输出文字
Windows 控制台默认是使用系统默认字符集进行文字输出。例如,系统要支持简体中文,一般设置字符集为 936(GBK)。当遇到同时要输出其他语言时,就会出现乱码,例如,输出韩文。
解决这个问题,需要解决两个关键点:
- 要以 UTF-16 字符集输出;Windows 内部支持的 Unicode,实际上是 UTF-16,并不是 UCS2。
- 控制台要设置成支持 UTF-16 字符集的字体。
UTF-16 字符集输出问题,可以使用SetConsoleOutputCP
函数将输出字符集改成 UTF-8。
字体问题,可以使用SetCurrentConsoleFontEx
函数将控制台字体设置成 MS Gothic。Windows 7 下只能设置成 Lucida Console,但 Lucida Console 对 UTF-16 字符集支持的不好,中文可以,韩文不可以。不过字体再怎么设置,在 Windows 内置控制台上还是不支持 emoji,而在 Windows Terminal 上,都不需要改字体就全支持。
示例代码:
#include <iostream> #include <locale> #include <codecvt> #include <windows.h> using namespace std; int main() { UINT oldcodepage = GetConsoleOutputCP(); CONSOLE_FONT_INFOEX oldFont; ZeroMemory(&oldFont, sizeof(oldFont)); oldFont.cbSize = sizeof(oldFont); GetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &oldFont); SetConsoleOutputCP(CP_UTF8); CONSOLE_FONT_INFOEX font; ZeroMemory(&font, sizeof(font)); font.cbSize = sizeof(CONSOLE_FONT_INFOEX); font.dwFontSize.X = 11; font.dwFontSize.Y = 18; font.FontFamily = 54; font.FontWeight = 400; //wcscpy(font.FaceName, L"Lucida Console"); wcscpy(font.FaceName, L"MS Gothic"); font.nFont = 12; SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &font); std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> u8cvt; locale lc(locale(""), new std::codecvt_utf8_utf16<wchar_t>()); wcout.imbue(lc); std::wstring wstr = L"中国"; std::string str = u8cvt.to_bytes(wstr); wcout << L"abcd" << endl; wcout << wstr << endl; cout << str << endl; printf("%s\n", str.c_str()); wstr = L"한식"; str = u8cvt.to_bytes(wstr); wcout << wstr << endl; cout << str << endl; printf("%s\n", str.c_str()); wstr = L"✂️ Copy and 📋 Paste Emoji 👍"; str = u8cvt.to_bytes(wstr); wcout << L"wcout << " << wstr << endl; cout << "cout << " << str << endl; printf("printf %s\n", str.c_str()); cin.get(); SetConsoleOutputCP(oldcodepage); SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &oldFont); return 0; }
在控制台中输出的效果:

在 Windows Terminal 输出的效果:

以上代码在 Visual Studio 2017 编译通过,源代码以 UTF-8 BOM 编码格式存储。