InternetReadFile not getting entire file

9.7k Views Asked by At

I have the following code to download some rss files from servers, but so far I'm just getting incomplete version of my rss file.(?) The code is as follows -

#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;   
}

I'm getting only almost half of my file and not from start but my output is seeming to be starting from somewhere in between the file and then to it's end. So where I'm going wrong? I checked that my rss file is at least gonna be 30kb large. So I have given the _SIZE const 307200 (300kb) and still it is not working? Please help me.

3

There are 3 best solutions below

9
Rhys Butler On

First of all, the problem you are having is that you are overwriting the same buffer and you are not clearing the data before each call of InternetReadFile. You also have not cleared the buffer before your first call. You are then throwing a potentially garbled mess of string and memory into a cout. This is very bad.

A quick fix would be to do this:

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;
}

This is not the most elegant way of doing it (far from it), but at least you should get the data you expect back.

Remember, InternetReadFile passes back a buffer of data, not necessarily a string! It could be an image, junk, and even if it is a string, in your case, it wont have a null byte to close it off. InternetReadFile reads raw bytes, NOT text.

A more elegant solution might start like this:

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;

Also, as a commenter added, you need to lay off the ALLCAPS for variables.

Hope this helps.

2
Remy Lebeau On

Try this instead:

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;
}
1
Lor David On
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;