【发布时间】:2017-04-07 16:33:51
【问题描述】:
我在为 Windows Compact 2013 编写的 C++ 应用程序中尝试从 Internet 下载文件时遇到了一个非常奇怪的问题。
BOOL WWW::Read(char* buffer, DWORD buffer_size)
{
memset(buffer, 0, buffer_size);
m_dwBytesRead = 0;
BOOL bResult = InternetReadFile(m_handle, buffer, buffer_size, &m_dwBytesRead);
if (!bResult)
{
DWORD dwLastError = GetLastError();
TCHAR *err;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
(LPTSTR)&err, 0, NULL))
{
LOGMSG(1, (TEXT("InternetReadFile failed at - (%u) %s\r\n"), dwLastError, err));
LocalFree(err);
}
}
// FUDGE
if (m_dwBytesRead == 0)
{
DWORD dwZeros = countZeros(buffer, buffer_size);
if (dwZeros < buffer_size)
{
m_dwBytesRead = buffer_size;
}
}
// END OF FUDGE
return bResult;
}
我从另一个成员函数重复调用上述函数如下
DWORD dwWritten;
while (!(Read(buffer, DOWNLOAD_BUFFER_SIZE) && m_dwBytesRead == 0))
{
WriteFile(m_hDownload, buffer, m_dwBytesRead, &dwWritten, NULL);
m_dwActualSize += dwWritten;
++m_dwChunks;
if (m_dwBytesRead > 0)
m_dwInactivity = 0;
else if (++m_dwInactivity > INACTIVITY_LIMIT)
return WDS_INACTIVITY;
}
没有 FUDGE,此函数第一次失败,但在后续调用中正常工作。我在第一次通过此函数调用时遇到的错误是
InternetReadFile failed at - (112) There is not enough space on the disk.
我不明白为什么在 READ 操作期间会收到“磁盘空间不足”错误。我检查了缓冲区是否已分配、可用且与预期大小匹配。事实上,当我检查缓冲区的内容时,我发现它已经填充了预期的字节数,但是 m_dwBytesRead 变量的内容仍然设置为 0。
如您所见,我试图通过检查缓冲区的内容以查看它是否已被填充,然后伪造 m_dwBytesRead 变量来围绕这个特定情况编写代码,但这只是让我临时解决的问题过了这个错误,我真的需要了解为什么会出现这个问题。
这个错误的后果(没有我的软糖)是数据被丢弃,我最终得到一个文件,它缺少第一个块,但在其他方面完全正确。因此 MD5 检查失败,我丢失了文件的第一部分。
我只是碰巧知道文件总是比我正在使用的块大小大,所以我的软糖会起作用,但我不喜欢在代码中使用这些不应该需要的可怕变通方法.
如果有人能解释导致问题的原因,将不胜感激。
我正在使用 Visual Studio 2013 C++(本机 Windows 应用程序,而不是 MFC),目标是 32 位和 Unicode,在 Windows Compact 2013 上运行。
非常感谢, 安德鲁
【问题讨论】:
-
在“常规”Windows 上运行它会发生什么?
-
感谢您的建议。我还没有在普通窗口上尝试过。我当然可以尝试(在星期一),看看是否有不同的行为。
-
一个更好的解决方法(如果可行的话)可能是第一次读取,总是失败,零长度。
-
谢谢哈利,这是另一个值得考虑的好建议,但正如您所说,这只是一种解决方法。在寻求“最佳”解决方案时,我会牢记这一点。
标签: c++ windows buffer readfile wininet