我正在尝试从URL下载图像文件。我按照使用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函数中的参数感到困惑,根据CURLOPT_WRITEFUNCTION:
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
"
ptr
指向传递的数据,该数据的大小为size
乘以nmemb
。"
......那么size和nmemb的含义是什么?
当尝试从网站下载数据时,我打印了前3个参数。看起来char*ptr
是存储数据的内存地址(如'char a[]'?),而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
当下载相同的URL时,nmemb和文件的打开次数经常发生变化。
我也对“sizeof(ptr)”感到困惑,它返回“4”(int的大小?)。我该如何使用“sizeof”来获取数据内存的大小,以便我可以证明数据大小为“size * nmemb”?
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;
}
谢谢!:)
fstream
,但它只用于写入。为什么不使用ofstream
呢?这样可以在编译时静态地确保你只使用它进行写入操作。此外,你还检查流是否打开,这是完全不必要的!只需使用ofstream file(out, ios_base::binary);
即可。稍后,你明确地调用close()
并clear()
流状态,这是多余的,因为之后你不再使用该流。相反,应该使用flush()
函数刷新流,并验证流状态以进行错误检查。尽管如此,所有这些都无法解释你遇到的问题。 - Ulrich Eckhardtsizeof
的定义是返回以char
为单位的大小,因此根据该定义,sizeof (char)
恰好为一。总是这样。 - Ulrich Eckhardtptr
只是指向数据的指针 - 它与提供给回调函数的数据量无关。您可以查看文档,了解Curl如何将数据缓冲区的大小传递给回调函数。除了通过下载已知数据量的URL进行测试之外,没有其他方法可以“证明”传递给回调函数的数据量为size * nmemb
- 这两个参数是Curl告诉您数据大小的方式。您只能相信Curl的说法。 - Michael Burr