WinAPI ReadFile 返回损坏的数据[关闭]
Posted
技术标签:
【中文标题】WinAPI ReadFile 返回损坏的数据[关闭]【英文标题】:WinAPI ReadFile returns corrupted data [closed] 【发布时间】:2019-06-30 06:15:43 【问题描述】:我正在我的 Visual C++ 项目中编写一个函数,它通过 WinAPI 以 2000 字节为增量读取文件的内容并将其作为 std::string 返回。
当文件远大于缓冲区(例如 100 KB)时会出现问题,我在有效数据中间的文件中的多个位置添加了垃圾。这是一个很长的0xcccccccc...
序列,由 3-4 个其他字节终止,通常出现在单词的中间。否则该函数不会失败,并且不会丢失任何有效数据。
我没有检查确切的位置,但似乎这发生在缓冲区大小增量(或缓冲区大小增量的乘数)时。如果我将缓冲区的大小增加到超过测试文件的大小,问题就会消失。是什么导致这种情况发生?我做错了什么?
std::string read_file(std::string filename)
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
std::string errortext("Error opening " + filename + ", bad handle value: " + to_string((int)hFile));
MessageBox(hwnd, errortext.c_str(), "Error", 0);
return "";
char buffer[2000] = "";
std::string entire_file = "";
DWORD dwBytesRead = 0;
while (ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL))
if (!dwBytesRead)
break;
entire_file += buffer;
CloseHandle(hFile);
return entire_file;
【问题讨论】:
为什么要使用winapi原生函数读取文件?std::ifstream
怎么了?
另外entire_file += buffer;
看起来有问题。您应该确保从缓冲区读取的内容是 nul 终止的(例如,在读取之前使用 memset()
)。
不,它没有。
如果读取完全填满缓冲区,memset
不会做插孔。您还必须为终止符保留一个额外的字节,否则错误将成为 bach。
循环似乎毫无意义。一次调用 ReadFile 即可读取整个文件。
【参考方案1】:
entire_file += buffer;
假设缓冲区是一个以空字符结尾的字符串,在你的情况下,它不是。
试试这个
entire_file.append(buffer, dwBytesRead);
这是一个很好的代码示例,本应敲响警钟,因为您没有使用dwBytesRead
变量(除了终止循环)。
【讨论】:
谢谢,我想可能就是这样。使用 calloc 初始化缓冲区并在循环中读取小于其大小的一个字节修复了问题。 不。这并不能解决问题。您将无法以这种方式正确处理最后的文本块。同样,我没有看到循环的意义。 @DavidHeffernan 怎么样?代码对我来说看起来不错。除非您事先知道文件的大小,否则也看不到如何在没有循环的情况下进行处理。如果您有改进或替代方案,很高兴看到一些实际代码。 你的代码没问题。 Liz 在上面的评论中描述的不是。最终连接不会以空值终止。 “除非你事先知道文件的大小”。我们会的,这是众所周知的。所以将字符串分配到那个长度并读入它的缓冲区。以上是关于WinAPI ReadFile 返回损坏的数据[关闭]的主要内容,如果未能解决你的问题,请参考以下文章