Libcurl:使用fstream :: write而不是fwrite

时间:2015-05-23 07:13:38

标签: c++ libcurl fstream

我试图从网址下载图片文件。我使用fwrite跟踪了示例,并且成功了。现在,我尝试使用fstream::write保存数据(ios::binary),但数据已损坏。这是我的代码:

#include"stdafx.h"
#include<fstream>
#include<iostream>
#include <curl/curl.h>
#include <string.h>

using namespace std;

size_t write_data(void *ptr, size_t size, size_t nmemb, char* out) {
    //void *ptr, size_t size, size_t nmemb, File* fp

    fstream file;
    if (file.is_open()){
        file.close();
        file.clear();
    }
    file.open(out, ios::out | ios::binary);
    if (file.is_open()){
        cout << "open successfully\n" << endl;

        file.write((char*)ptr, nmemb*size);  // Does it correct?
    };
    // fwrite(ptr,size,nmemb,fp);
    file.close();
    file.clear();
    cout <<"\n sizeof(ptr): " << sizeof(ptr) //size of ptr[0]?
         <<"\n sizeof(char): " << sizeof(char)
         <<"\n size: " << size
         <<"\n nmemb: " << nmemb<< endl;
         return size*nmemb;
}

我对write_data中的参数感到困惑。 根据{{​​3}}

  

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);

     

&#34; ptr指向已投放的数据,该数据的大小为size乘以nmemb。&#34;

......那么尺寸和nmemb的含义是什么?

当试图从网站下载数据时,我打印了前3个参数。 char*ptr似乎是存储数据的内存地址(&#39; char a []&#39;?),而size是元素的大小,nmemb是数字要素。所以数据大小=大小* nmemb。我是对的吗?

输出也令人困惑:

open successfully
sizeof(ptr):4
sizeof(char):1
size:1
nmemb:2715 
open successfully
sizeof(ptr):4
sizeof(char):1
size:1
nmemb:4865
download successfully

下载相同的网址,文件和文件时开放时间经常变化。

我也对&#39; sizeof(ptr)&#39;感到困惑,它返回&#39; 4&#39;(int的大小?)。我怎样才能使用&#39; sizeof&#39;为了获得数据内存的大小,我可以证明 数据大小是&#39; size * nmemb&#39;

CURLcode download(char* url,char* out){
    CURL *curl = NULL;
    //FILE *fp = NULL;
    CURLcode res;
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, out);    //fp
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
        return res;
    }
    else
    {
        return CURLE_FAILED_INIT;
    }
}    

int main()
{
    CURLcode res = download("http://XXXXXX.gif", "D:\\test.gif");
    if (CURLE_OK == res)
        cout << "download successfully.\n" << endl;
    else
        cout<<"cannot download.\n"<<endl;
    return 0;
}

谢谢! :)

1 个答案:

答案 0 :(得分:1)

每个文件可以多次回调。每次调用函数时都不应创建新的文件流 - 您应该使用用户数据参数传递它。否则,您将继续覆盖文件开头的数据。

以下是一个示例实现:

size_t write_data(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    std::ofstream *out = static_cast<std::ofstream *>(userdata);
    size_t nbytes = size * nmemb;
    out->write(ptr, nbytes);
    return nbytes;
}

您还需要使用参数curl_easy_setopt调整对CURLOPT_WRITEDATA的调用,以实际传递您的文件流。确保在函数运行时流不会超出范围!

CURLcode download(char* url, char* out) {
    CURL *curl = NULL;
    std::ofstream output(out, ios::binary);
    CURLcode res;
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &output);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
        return res;
    }
    else
    {
        return CURLE_FAILED_INIT;
    }
}