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

Windows API ReadFile()每读取两个字符就跳过一个问题排查

问题根因

你遇到的字符丢失问题完全是代码里的编码逻辑错误导致的,和CreateFile、ReadFile接口本身无关,错误点如下:

  • 你的words.txt是单字节编码文本(ASCII/GBK/UTF-8无BOM均属于这类),每个字符占1字节,但你用双字节的WCHAR数组作为读取缓冲区,相当于把相邻2个单字节字符拼接成了1个WCHAR值。
  • 后续你把WCHAR数组转std::string时,默认只取每个WCHAR的低8位,高8位直接丢弃,正好对应每2个原始字符丢1个,完全符合你描述的HELLO变成HLO的现象。
  • 额外冗余的多次编码转换(WCHAR转string又转回WCHAR)进一步放大了错误,完全没有必要。
修复方案

根据你的文本文件编码选择对应方案即可:

方案1:文件为单字节编码(ASCII/GBK/UTF-8)

直接用char数组承接读取的字节,再按编码规则转成WCHAR即可,修改后代码如下:

void init(HDC hdc)
{
    HANDLE hFile;
    LPCSTR fileName = "c:\\Users\\kanaa\\Desktop\\code\\HW2_StarterCode\\words.txt";
    hFile = CreateFileA(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD dwFileSize = GetFileSize(hFile, NULL);
    DWORD dwBytesRead;
    // 用char数组存单字节内容
    char* buffer = new char[dwFileSize + 1];  
    buffer[dwFileSize] = 0;
    bool read = ReadFile(hFile, buffer, dwFileSize, &dwBytesRead, NULL);
    CloseHandle(hFile);
    
    if (read) {
        // 单字节转WCHAR,GBK编码用CP_ACP,UTF-8编码用CP_UTF8
        int wlen = MultiByteToWideChar(CP_ACP, 0, buffer, dwFileSize, NULL, 0);
        WCHAR* wbuf = new WCHAR[wlen + 1];
        MultiByteToWideChar(CP_ACP, 0, buffer, dwFileSize, wbuf, wlen);
        wbuf[wlen] = 0;
        parse(wbuf, hdc);
        delete[] wbuf;
    }
    delete[] buffer;
}

// parse可直接简化,不用再转码
void parse(const WCHAR* wcword, HDC hdc)
{
    Graphics graphics(hdc);
    drawText(&graphics, wcword);
}

方案2:文件为UTF-16LE编码(Windows下的Unicode格式)

无需转码,只需跳过开头的2字节BOM即可直接使用:

void init(HDC hdc)
{
    HANDLE hFile;
    LPCSTR fileName = "c:\\Users\\kanaa\\Desktop\\code\\HW2_StarterCode\\words.txt";
    hFile = CreateFileA(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD dwFileSize = GetFileSize(hFile, NULL);
    DWORD dwBytesRead;
    WCHAR* buffer = new WCHAR[dwFileSize / 2 + 1];  
    buffer[dwFileSize / 2] = 0;
    bool read = ReadFile(hFile, buffer, dwFileSize, &dwBytesRead, NULL);
    CloseHandle(hFile);
    if (read) {
        // 跳过UTF-16 LE的BOM头(0xFEFF)
        const WCHAR* text = buffer;
        if (buffer[0] == 0xFEFF) text++;
        parse(text, hdc);
    }
    delete[] buffer;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:45:02