对于在英文Windows(XP,Vista或7)上使用Visual Studio 2008编译的C ++控制台应用程序,是否可以使用cout或wcout打印到控制台并正确显示UTF-8编码的日语?
对于在英文Windows(XP,Vista或7)上使用Visual Studio 2008编译的C ++控制台应用程序,是否可以使用cout或wcout打印到控制台并正确显示UTF-8编码的日语?
这应该可以正常工作:
#include <cstdio>
#include <windows.h>
#pragma execution_character_set( "utf-8" )
int main()
{
SetConsoleOutputCP( 65001 );
printf( "Testing unicode -- English -- Ελληνικά -- Español -- Русский. aäbcdefghijklmnoöpqrsßtuüvwxyz\n" );
}
不知道它是否会影响任何东西,但源文件被保存为Unicode(带签名的UTF-8) - 代码页65001 ,位于文件-> 高级保存选项...。
项目-> 属性-> 配置属性->常规->字符集设置为使用Unicode字符集。
有人说需要更改控制台字体为Lucida Console,但在我的电脑上,它显示为Consolas和Lucida Console。
默认情况下,Windows控制台使用OEM代码页显示输出。
要将代码页更改为Unicode,请在控制台中输入chcp 65001
,或尝试通过SetConsoleOutputCP
以编程方式更改代码页。
请注意,您可能需要更改控制台的字体,以便其具有Unicode范围内的字形。
这是MVP Michael Kaplan的一篇文章,讲述了如何通过控制台正确输出UTF-16。您可以将UTF-8转换为UTF-16并输出。
在应用程序启动时,控制台设置为默认的OEM437 CP。
我试图将Unicode文本输出到stdout,在控制台切换到UTF8模式_setmode(_fileno(stdout), _O_U8TEXT);即使使用Lucida TT字体,仍然无法在屏幕上显示。
如果控制台重定向到文件,则会创建正确的UTF8文件。
最后我很幸运地发现解决方法。我添加了一行代码"info.FontFamily = FF_DONTCARE;",它现在可以正常工作了。
希望这对你有所帮助。
void SetLucidaFont()
{
HANDLE StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_FONT_INFOEX info;
memset(&info, 0, sizeof(CONSOLE_FONT_INFOEX));
info.cbSize = sizeof(CONSOLE_FONT_INFOEX); // prevents err=87 below
if (GetCurrentConsoleFontEx(StdOut, FALSE, &info))
{
info.FontFamily = FF_DONTCARE;
info.dwFontSize.X = 0; // leave X as zero
info.dwFontSize.Y = 14;
info.FontWeight = 400;
_tcscpy_s(info.FaceName, L"Lucida Console");
if (SetCurrentConsoleFontEx(StdOut, FALSE, &info))
{
}
}
}
system
调用:#include <stdlib.h>
#include <stdio.h>
int main() {
system("chcp 65001");
printf("%s\n", "中文");
}
仅供参考:
'ANSI'是指windows-125x,用于win32应用程序,而'OEM'是指控制台/MS-DOS应用程序使用的代码页。
可以使用GetOEMCP()和GetACP()函数检索当前活动的代码页。
为了正确输出到控制台,您应该:
确保当前OEM代码页支持您想要输出的字符
(如果需要,使用SetConsoleOutputCP进行适当设置)
将字符串从当前ANSI代码(win32)转换为控制台OEM代码页
以下是一些实用工具:
// Convert a UTF-16 string (16-bit) to an OEM string (8-bit)
#define UNICODEtoOEM(str) WCHARtoCHAR(str, CP_OEMCP)
// Convert an OEM string (8-bit) to a UTF-16 string (16-bit)
#define OEMtoUNICODE(str) CHARtoWCHAR(str, CP_OEMCP)
// Convert an ANSI string (8-bit) to a UTF-16 string (16-bit)
#define ANSItoUNICODE(str) CHARtoWCHAR(str, CP_ACP)
// Convert a UTF-16 string (16-bit) to an ANSI string (8-bit)
#define UNICODEtoANSI(str) WCHARtoCHAR(str, CP_ACP)
/* Convert a single/multi-byte string to a UTF-16 string (16-bit).
We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string.
*/
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
size_t len = strlen(str) + 1;
int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
return wstr;
}
/* Convert a UTF-16 string (16-bit) to a single/multi-byte string.
We take advantage of the WideCharToMultiByte function that allows to specify the charset of the output string.
*/
LPSTR WCHARtoCHAR(LPWSTR wstr, UINT codePage) {
size_t len = wcslen(wstr) + 1;
int size_needed = WideCharToMultiByte(codePage, 0, wstr, len, NULL, 0, NULL, NULL);
LPSTR str = (LPSTR) LocalAlloc(LPTR, sizeof(CHAR) * size_needed );
WideCharToMultiByte(codePage, 0, wstr, len, str, size_needed, NULL, NULL);
return str;
}
chcp 65001
以将代码页更改为UTF-8的代码页。如果有人需要从文件中读取UTF-8并在控制台中打印,可以尝试使用wifstream
,即使在Visual Studio调试器中正确显示UTF-8单词(我正在处理繁体中文),参考this post:
#include <sstream>
#include <fstream>
#include <codecvt>
std::wstring readFile(const char* filename)
{
std::wifstream wif(filename);
wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
std::wstringstream wss;
wss << wif.rdbuf();
return wss.str();
}
// usage
std::wstring wstr2;
wstr2 = readFile("C:\\yourUtf8File.txt");
wcout << wstr2;