You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Windows控制台中setlocale会导致fputs输出乱码?

Windows控制台程序中stdout与LC_CTYPE、SetConsoleOutputCP的行为差异问题

我的Windows系统ANSI代码页为GBK,开发控制台程序时发现以下特殊行为:

测试代码1(fputs操作stdout与文件)

// SetConsoleOutputCP(65001); // 代码页936或65001均不影响结果
char utf8[] = { 0xE4, 0xB8, 0xAD, 0xE5, 0x9B, 0xBD, '+', '\n', '\0'}; // “中国+”的UTF-8字节序列
char gbk[] = { 0xD6, 0xD0, 0xB9, 0xFA, '-', '\n', '\0' }; // “中国-”的GBK(936)字节序列

char* currentLocale = setlocale(LC_CTYPE, "zh_CN.UTF-8"); // "zh_CN.UTF-8" 

FILE* file = fopen("G:/1.txt", "wb");
fputs(utf8, stdout); // 输出“中国+”
fputs(gbk, stdout); // 无输出
fputs(utf8, file);
fputs(gbk, file);

currentLocale = setlocale(LC_CTYPE, "chs.936"); // "Chinese_China.936"

fputs(utf8, stdout); // 输出“涓浗+” 
fputs(gbk, stdout); // 输出“中国-”
fputs(utf8, file);
fputs(gbk, file);

使用命令将标准输出重定向至文件:

charset.exe > G:/stdout.txt

对比重定向的stdout.txt与代码中直接写入的file.txt的十六进制内容:

first fputssecond fputsthird fputsfourth fputs
stdout.txtE4 B8 AD E5 9B BD 2B 0D 0AD6 D0 B9 FA 2D 0D 0AE4 B8 AD E5 9B BD 2B 0D 0AD6 D0 B9 FA 2D 0D 0A
file.txtE4 B8 AD E5 9B BD 2B 0AD6 D0 B9 FA 2D 0AE4 B8 AD E5 9B BD 2B 0AD6 D0 B9 FA 2D 0A

可见:当stdout重定向到文件时,修改LC_CTYPE前后,fputs(str, stdout)输出的字节序列完全一致;但直接输出到控制台时,stdout的显示结果随LC_CTYPE的改变而变化。

最初怀疑这与SetConsoleOutputCP有关,但测试发现无论设置代码页为936还是65001,都不影响上述代码的控制台输出结果。

测试代码2(WriteFile操作STD_OUTPUT_HANDLE)

SetConsoleOutputCP(65001); // 设为936时GBK输出正常,设为65001时UTF-8输出正常
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwBytesWritten;

char* currentLocale = setlocale(LC_CTYPE, "zh_CN.UTF-8"); // "zh_CN.UTF-8"

WriteFile(hStdout, utf8, sizeof(utf8), &dwBytesWritten, NULL); // 输出“中国+”
WriteFile(hStdout, gbk, sizeof(gbk), &dwBytesWritten, NULL); // 输出“�й�-”

currentLocale = setlocale(LC_CTYPE, "chs.936"); // "Chinese_China.936"

WriteFile(hStdout, utf8, sizeof(utf8), &dwBytesWritten, NULL); // 输出“中国+”
WriteFile(hStdout, gbk, sizeof(gbk), &dwBytesWritten, NULL); // 输出“�й�-”

测试结果:WriteFile仅受SetConsoleOutputCP影响,不受LC_CTYPE改变的影响。

核心疑问

STD_OUTPUT_HANDLE与stdout均指向控制台,理论上相同字节序列的显示应该一致,但实际结果完全不同:

  • 为什么输出到控制台时,stdout的表现会随LC_CTYPE改变,而重定向到文件时字节序列无变化?
  • 为什么SetConsoleOutputCP不影响stdout的控制台输出,却能影响WriteFile的输出?

内容的提问来源于stack exchange,提问作者ok im

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:13:25