在cmd上打印到stderr无法打印非ASCII UTF-8文本的第一个字符
这就是我的代码的样子:在cmd上打印到stderr无法打印非ASCII UTF-8文本的第一个字符,c,windows,utf-8,printf,stderr,C,Windows,Utf 8,Printf,Stderr,这就是我的代码的样子: #include <windows.h> #include <stdio.h> int main() { SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_FONT_INFOEX cfie; ZeroMemory(&cfie, s
#include <windows.h>
#include <stdio.h>
int main()
{
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_FONT_INFOEX cfie;
ZeroMemory(&cfie, sizeof(cfie));
cfie.cbSize = sizeof(cfie);
lstrcpyW(cfie.FaceName, L"Lucida Console");
SetCurrentConsoleFontEx(hStdOut, 0, &cfie);
fprintf(stderr, "нијe\n");
}
当打印行被替换为:printf(“ајe\n”)代码>
输出是预期的:
нијe
我可能应该提到,我用MinGW GCC编译了它,并在CMD中运行了它。只有SetConsoleOutputCP()
对我有效。即使是“Consolas”作为字体也能提供正确的字符
#include <windows.h>
#include <stdio.h>
int main()
{
fprintf(stderr, "нијe\n");
SetConsoleOutputCP(CP_UTF8);
fprintf(stderr, "нијe\n");
}
操作系统为Windows 10(1903),在命令提示符下运行,命令行如下:
> for %i in (850 1252 65001) do ( mode con cp select=%i & console.exe & mode con /status )
它生成以下输出(德语区域设置,抱歉):
请注意:如果您想使用stderr
的句柄,请使用STD\u ERROR\u HANDLE
而不是STD\u OUTPUT\u HANDLE
,对windows api了解不多,但似乎您正在设置与winapi“stdout”等效的句柄。您仍然在编写“stderr”。无论是stdout还是stderr,您的代码都不应该假定该文件是控制台屏幕缓冲区。您应该检测屏幕缓冲区并调整处理文件的方式。控制台通常使用UTF-8,尤其是在Windows 8之前。CFILE
streams通过缓冲流,偶尔在两次写入中拆分UTF-8序列,使情况变得更糟,控制台不支持任何版本的Windows。通常我建议使用宽字符函数,如wprintf
,并将控制台类型文件设置为UTF-16模式,将所有其他类型文件设置为UTF-8模式,例如\u setmode(\u file(stderr),\u O\u U16TEXT)
。但是,我不知道MinGW使用的旧系统CRT(msvcrt.dll)是否支持在UTF-16模式下切换到控制台的宽字符API。我认为这仅限于较新版本的VC++。如果是这种情况,那么对于控制台I/O,我建议完全直接使用控制台API放弃C标准I/O,即WriteConsoleW
和ReadConsoleW
这在技术上是正确的,因为通常stdout和stderr可能引用不同的文件。(默认情况下,它们引用相同的控制台屏幕缓冲区。)但是,这与问题无关。OP仅使用句柄修改屏幕缓冲区的字体。这与将“呃”(U+043D)写入屏幕的方式无关��", i、 e.两个替换字符(U+FFFD)。
> gcc -Wall -Wextra -pedantic console.c -o console.exe
> for %i in (850 1252 65001) do ( mode con cp select=%i & console.exe & mode con /status )
> (mode con cp select=850 & console.exe & mode con /status )
Status von Gerät CON:
---------------------
Zeilen: 9999
Spalten: 120
Wiederholrate: 31
Verzögerungszeit:1
Codepage: 850
ð¢ð©Ðÿe
нијe
Status von Gerät CON:
---------------------
Zeilen: 9999
Spalten: 120
Wiederholrate: 31
Verzögerungszeit:1
Codepage: 850
> (mode con cp select=1252 & console.exe & mode con /status )
Status von Gerät CON:
---------------------
Zeilen: 9999
Spalten: 120
Wiederholrate: 31
Verzögerungszeit:1
Codepage: 1252
нијe
нијe
Status von Gerät CON:
---------------------
Zeilen: 9999
Spalten: 120
Wiederholrate: 31
Verzögerungszeit:1
Codepage: 1252
> (mode con cp select=65001 & console.exe & mode con /status )
Status von Gerät CON:
---------------------
Zeilen: 9999
Spalten: 120
Wiederholrate: 31
Verzögerungszeit:1
Codepage: 65001
нијe
нијe
Status von Gerät CON:
---------------------
Zeilen: 9999
Spalten: 120
Wiederholrate: 31
Verzögerungszeit:1
Codepage: 65001