【问题标题】:Windows API ReadFile() skips one out of every two charactersWindows API ReadFile() 跳过每两个字符中的一个
【发布时间】:2021-12-08 02:17:01
【问题描述】:

我的目标是读取文件中的所有文本。出于某种原因,每当我从文件中读取并打印结果(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);
}

【问题讨论】:

  • 文件是如何生成的以及使用何种编码?
  • 您的代码可能假定为宽字符,但事实并非如此。
  • 这可能是对的,500。
  • std::wstring(to.begin(), to.end()) - 这不会有什么好处。为什么这个“请丢弃我的字符串数据”实现仍然进行循环?
  • 请不要在您的问题中编辑答案

标签: c++ windows winapi gdi


【解决方案1】:

问题在于 WCHAR 缓冲区。以下是更正

    CHAR* buffer = new CHAR[dwFileSize/sizeof(char) + 1];  
    bool read = ReadFile(hFile, buffer, dwFileSize, &dwBytesRead, NULL);
    buffer[dwBytesRead] = 0;

【讨论】:

  • 谢谢,我马上改
【解决方案2】:

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

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

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

改为使用char[] 缓冲区处理文件数据。但是,有easier ways可以将7/8位文件数据读入std::string

最后,在此声明中:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-20
    • 1970-01-01
    • 2015-04-12
    • 2017-04-13
    • 1970-01-01
    相关资源
    最近更新 更多