gpt4 book ai didi

c++ - Libcurl:使用 fstream::write 而不是 fwrite 时图像损坏

转载 作者:太空狗 更新时间:2023-10-29 21:40:42 26 4
gpt4 key购买 nike

我正在尝试从 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 points to the delivered data, and the size of that data is size multiplied with nmemb."

......那么size和nmemb是什么意思呢?

当尝试从网站下载数据时,我打印了前 3 个参数。似乎char*ptr是数据存储的内存地址(如'char a[]'?),size是元素的大小,nmemb是元素的数量.所以数据大小=size * 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”(整数的大小?)。如何使用“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;
}

谢谢! :)

最佳答案

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

这是一个示例实现:

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

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

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

关于c++ - Libcurl:使用 fstream::write 而不是 fwrite 时图像损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30410027/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com