使用Windows API读取打印UTF-16LE文件无输出问题排查
解决Windows API读取UTF-16LE文件后控制台无输出问题
问题根源
你的代码读取UTF-16LE文件的逻辑是正确的,但控制台默认输出编码不支持直接打印宽字符(wchar_t),导致wcout输出的中文无法显示。另外,循环打印101个wchar_t会包含未读取的空字符,也会干扰正常输出。
修复步骤
1. 切换控制台输出编码为UTF-16
Windows控制台默认使用GBK或系统默认代码页,需手动切换到UTF-16(代码页1200)来适配宽字符输出:
SetConsoleOutputCP(CP_UTF16);
2. 仅打印有效读取字符
ReadFile返回的win_Transmission是读取的字节数,UTF-16每个字符占2字节,因此实际有效字符数为win_Transmission / sizeof(wchar_t),循环时只打印这些有效字符即可,避免输出空字符。
3. 优化C++宽字符流输出(可选)
默认情况下C++流与C标准库同步,可能影响宽字符输出效率和正确性,可禁用同步:
ios_base::sync_with_stdio(false); wcin.tie(nullptr); wcout.tie(nullptr);
修改后的完整代码
#include <Windows.h> #include <iostream> #include <cstddef> #include <cstdint> using namespace std; int main() { // 设置控制台输出为UTF-16编码 SetConsoleOutputCP(CP_UTF16); // 禁用流同步,优化宽字符输出 ios_base::sync_with_stdio(false); wcin.tie(nullptr); wcout.tie(nullptr); HANDLE win_file = CreateFile2( L"C:\\win32tese.txt", GENERIC_READ, // 仅保留读权限,无需写权限 FILE_SHARE_READ, // 添加共享读权限,避免文件被独占 OPEN_EXISTING, NULL ); if (win_file == INVALID_HANDLE_VALUE) { wcout << L"Failed to open file, error code: " << GetLastError() << endl; return -1; } wchar_t win_buffer[101] = {}; DWORD win_Transmission = 0; BOOL win_Read = ReadFile( win_file, win_buffer, // 直接传缓冲区地址,无需取址符 sizeof(win_buffer) - sizeof(wchar_t), // 预留一个位置存终止符,防止溢出 &win_Transmission, NULL ); wcout << L"Bytes transferred: " << win_Transmission << endl; if (!win_Read) { wcout << L"Read operation failed, error code: " << GetLastError() << endl; } else { size_t char_count = win_Transmission / sizeof(wchar_t); // 处理UTF-16LE的BOM(如果文件包含) size_t start_idx = (char_count > 0 && win_buffer[0] == 0xFEFF) ? 1 : 0; for (size_t i = start_idx; i < char_count; ++i) { wcout << win_buffer[i]; } wcout << endl; } CloseHandle(win_file); return 0; }
额外说明
- 打开文件时,去掉不必要的
GENERIC_WRITE权限,添加FILE_SHARE_READ可避免因文件被独占导致的打开失败; - 如果你的UTF-16LE文件包含BOM(开头为
0xFFFE),代码中已添加判断跳过BOM,避免输出无效字符; ReadFile的缓冲区大小设置为sizeof(win_buffer) - sizeof(wchar_t),确保预留一个位置存放字符串终止符,防止缓冲区溢出。
内容的提问来源于stack exchange,提问作者玩家蒸汽
相关产品推荐
相关产品推荐

