2013-07-26 8 views
1

У меня есть следующий код, чтобы загрузить некоторые RSS файлы с серверов, но до сих пор я просто получаю неполную версию моего файла RSS код выглядит следующим образом. (?) -InternetReadFile не получает весь файл

#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-файл, по крайней мере, будет 30 КБ. Итак, я дал _SIZE const 307200 (300kb) и все еще не работает? Пожалуйста, помогите мне.

+0

Ведения конвенции и стандарты в виде позволят легче читать и помогут вам получить лучшие ответы кода. Идентификаторы UPPER_CASE обычно относятся только к макросам, а идентификаторы, начинающиеся с подчеркивания в глобальной области, зарезервированы для использования компилятором. –

+0

Хорошо, будем иметь в виду. Но можете ли вы помочь мне с моей проблемой? –

ответ

-1

Прежде всего, проблема заключается в том, что вы перезаписываете один и тот же буфер, и вы не очищаете данные перед каждым вызовом 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 для переменных.

Надеюсь, это поможет.

+1

Хорошо, я понимаю, что вы имеете в виду. Но когда я скомпилировал ваш второй подход, я получил ошибку - 55 C: \ Users \ Maximus7 \ Documents \ Untitled1.cpp: 24 вызов перегруженного 'append (BYTE [307200], DWORD &)' неоднозначен. Что это? –

+1

И на странной стороне первый подход все еще дает мне те же результаты? Также я нашел что-то интересное, что для каждого «\ n», включенного после 'cout << _ DATA_RECIEVED', я получил меньше! Это связано с моей проблемой? –

+1

Извините, я скорректировал код, небольшую ошибку. Я изменил строку resultRss.append ((char *) _ DATA_RECIEVED, NO_BYTES_READ); , Поскольку мы определяем его как байт (unsigned char *), нам нужно выставить _DATA_RECIEVED как (char *). Или вы можете заменить BYTE на CHAR acain. Второй пример - просто заставить вас думать о более надежных альтернативах, например, хранить данные, а не просто выводить их на экран. –

0

Попробуйте вместо этого:

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

Извините, но он не работает. Я пробовал другие файлы размером около 30 КБ, и все они дали мне ту же ошибку, что и отсутствующие данные на выходе. –

+0

Вы проверили, имеют ли данные в нем нулевые символы? Вы пытались сохранить данные в файл, а не выводить его на экран? Экранный вывод не может отображать двоичные данные. Поэтому проверьте фактические данные, а не результаты экрана. –