InternetReadFile未获取整个文件

InternetReadFile not getting entire file

本文关键字:文件 获取 InternetReadFile      更新时间:2023-10-16

我有以下代码从服务器下载一些rss文件,但到目前为止,我得到的只是我的rss文件的不完整版本。(?)代码如下-

#include<iostream>
#include<conio.h>
#include<stdio.h>
#include<string>
#include<cstring>
#include<wininet.h> 
using namespace std;
const int _SIZE = 307200;
int WEB_GET_DATA(char* WEB_URL){
    HINTERNET WEB_CONNECT = InternetOpen("Default_User_Agent",INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0);
    if(!WEB_CONNECT){
       cout<<"Connection Failed or Syntax error";
       return 0;
    }
    HINTERNET WEB_ADDRESS = InternetOpenUrl(WEB_CONNECT,WEB_URL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION, 0);
    if(!WEB_ADDRESS){
          cout<<"ERROR...n";
          return 0;
    }
    char _DATA_RECIEVED[_SIZE];
    DWORD NO_BYTES_READ = 0;
    while(InternetReadFile(WEB_ADDRESS,_DATA_RECIEVED,_SIZE,&NO_BYTES_READ)&&(NO_BYTES_READ)){
        cout<<_DATA_RECIEVED;
    }
    InternetCloseHandle(WEB_ADDRESS);
    InternetCloseHandle(WEB_CONNECT);
    return 0;
}
int main(){
  WEB_GET_DATA("http://themoneyconverter.com/rss-feed/AED/rss.xml");
  getch();
  return 0;   
}

我只得到了几乎一半的文件,而不是从一开始,但我的输出似乎是从文件之间的某个地方开始,然后到它的结尾。那么我哪里错了?我检查了我的rss文件是否至少有30kb大。所以我给了_SIZE常量307200(300kb),但它仍然不起作用?请帮帮我。

试试这个:

int WEB_GET_DATA(char* WEB_URL)
{
    HINTERNET WEB_CONNECT = InternetOpen("Default_User_Agent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (!WEB_CONNECT)
    {
       cout << "Connection Failed or Syntax error" << endl;
       return 0;
    }
    HINTERNET WEB_ADDRESS = InternetOpenUrl(WEB_CONNECT, WEB_URL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION, 0);
    if (!WEB_ADDRESS)
    {
        cout << "ERROR..." << endl;
        InternetCloseHandle(WEB_CONNECT);
        return 0;
    }
    DWORD DATA_SIZE = _SIZE;
    char *_DATA_RECIEVED = new char[DATA_SIZE];
    DWORD NO_BYTES_READ = 0;
    do
    { 
        if (InternetReadFile(WEB_ADDRESS, _DATA_RECIEVED, DATA_SIZE, &NO_BYTES_READ))
        { 
            if (NO_BYTES_READ == 0)
                break;
            cout << string(_DATA_RECIEVED, NO_BYTES_READ);
        }
        else
        {
            if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            {
                cout << "Read error" << endl;
                break;
            }
            delete[] _DATA_RECIEVED;
            DATA_SIZE += _SIZE;
            _DATA_RECIEVED = new char[DATA_SIZE];
        }
    }
    while (true);
    InternetCloseHandle(WEB_ADDRESS);
    InternetCloseHandle(WEB_CONNECT);
    return 0;
}
char buffer[200000];
DWORD bytes_read = 0;
DWORD currbytes_read;
do
{
    bRead = InternetReadFile(file_handle, buffer + bytes_read, 200000 - bytes_read, &currbytes_read);
    bytes_read += currbytes_read;
} while (bRead && currbytes_read);
buffer[bytes_read] = 0;

首先,您遇到的问题是覆盖了相同的缓冲区,并且在每次调用InternetReadFile之前没有清除数据。您在第一次调用之前也没有清除缓冲区。然后,你将一个可能混乱的字符串和内存扔进了一个cout。这太糟糕了。

一个快速的解决办法是这样做:

BYTE _DATA_RECIEVED[_SIZE]; // BYTE is a char, but its clearer now its not guaranteed to be a string!
BOOL ret = TRUE;
DWORD NO_BYTES_READ = 0;
while(ret){
    memset(_DATA_RECIEVED, 0, _SIZE); // clear the buffer
    ret = InternetReadFile(WEB_ADDRESS,_DATA_RECIEVED,_SIZE,&NO_BYTES_READ);
    if(NO_BYTES_READ > 0)
        cout<<_DATA_RECIEVED;
}

这不是最优雅的方法(远非如此),但至少你应该得到你期望的数据。

请记住,InternetReadFile会传回一个数据缓冲区,而不一定是字符串!它可能是一个图像,垃圾,即使它是一个字符串,在你的情况下,它也不会有一个空字节来关闭它。InternetReadFile读取原始字节,而不是文本。

一个更优雅的解决方案可能像这样开始

std::string resultRss;
BYTE _DATA_RECIEVED[_SIZE];
DWORD NO_BYTES_READ = 0;
while(InternetReadFile(WEB_ADDRESS,_DATA_RECIEVED,_SIZE,&NO_BYTES_READ)){
    resultRss.append((char*)_DATA_RECIEVED, NO_BYTES_READ); //doesn't matter about null-byte because we are defining the number of bytes to append. This also means we don't NEED to clear the memory, although you might want to.
}
//output final result
cout << resultRss;

此外,正如一位评论者补充的那样,您需要取消变量的ALLCAPS。

希望这能有所帮助。