首页 > 解决方案 > Windows API ReadFile() 跳过每两个字符中的一个

问题描述

我的目标是读取文件中的所有文本。出于某种原因,每当我从文件中读取并打印结果(drawText)时,缓冲区似乎每两个位置跳过一个字符。HELLO 将变为 HLO,而 SCAVENGER 将变为 SAEGR。

这适用于 Windows API。我想知道 CreateFile() 和 ReadFile() 是否很好,以及是否是其他原因导致了这个问题。

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);
    std::wstring wstr(buffer);
    std::string str(wstr.begin(), wstr.end());
    delete[] buffer;
    CloseHandle(hFile);
    if (read) parse(str, hdc);
}

void parse(std::string word, HDC hdc)
{
    std::string to = word;
    std::wstring wword = std::wstring(to.begin(), to.end());
    const WCHAR* wcword = wword.c_str();
    Graphics graphics(hdc);
    drawText(&graphics, wcword);
}

标签: c++windowswinapigdi

解决方案


您正在使用wchar_t[]缓冲区处理文件数据。 wchar_t在 Windows 上为 2 个字节。所以,在声明中:

std::string str(wstr.begin(), wstr.end());

您一次遍历文件数据 2 个字节,将每个字节对解释为一个wchar_t被截断为 1-byte的单个字节char,丢弃另一个字节。这就是为什么你str最终会跳过所有其他角色。

改为使用char[]缓冲区处理文件数据。但是,有更简单的方法可以将 7/8 位文件数据读入std::string.

最后,在此声明中:

std::wstring wword = std::wstring(to.begin(), to.end());

这不是将 a 转换std::string为 a的正确方法std::wstring。您所做的只是遍历chars 将每个原样转换为 2-byte wchar_t。Windows API 期望wchar_t字符串以 UTF-16 编码,而您的代码不会转换成这种格式。您需要使用MultiByteToWideChar(),std::wstring_convert或其他等效的 Unicode 库调用来执行该转换。在这种情况下,您首先需要知道源文件的编码才能正确地将其转换为 Unicode。


推荐阅读