c++ - 如何使用 libcurl c++ 从 url 保存 XML 文件
问题描述
如何使用 libcurl c++ 从 URL 保存 XML 文件,以便稍后使用 pugixml 加载它。我已经尝试过了,但它不起作用
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t written = fwrite(ptr, size, nmemb, stream);
return written;
}
...
CURL *curl;
FILE *fp;
CURLcode result;
char *c_url = "http://some_url.xml";
char outfilename[FILENAME_MAX] = "sth.xml";
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, c_url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
result = curl_easy_perform(curl);
}
curl_global_init(CURL_GLOBAL_DEFAULT);
...
curl_easy_cleanup(curl);
curl_global_cleanup();
fclose(fp);
解决方案
通过将 设置为 修复错误后char*
,const
如下所示:
char const* c_url = "http://some_url.xml";
你的代码对我来说很好。
但是,您并不总是希望将收到的数据写入接收磁盘。有时您只是想将它保存在内存中以随时使用它。
在这里,我编写了一个函数来将 URL 的目标下载到std::string
你可以做任何你想做的事情。我还使用智能指针使代码异常安全且通常更安全。
// write the data into a `std::string` rather than to a file.
std::size_t write_data(void* buf, std::size_t size, std::size_t nmemb,
void* userp)
{
if(auto sp = static_cast<std::string*>(userp))
{
sp->append(static_cast<char*>(buf), size * nmemb);
return size * nmemb;
}
return 0;
}
// To make the function thread safe you can use a smart pointer to
// hold your CURL session pointer.
// A deleter to use in the smart pointer for automatic cleanup
struct curl_dter{void operator()(CURL* curl) const
{ if(curl) curl_easy_cleanup(curl); }};
// A smart pointer to automatically clean up out CURL session
using curl_uptr = std::unique_ptr<CURL, curl_dter>;
// download the URL into a `std::string`.
std::string get_url(std::string const& url)
{
std::string data;
if(auto curl = curl_uptr(curl_easy_init()))
{
curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &data);
CURLcode ec;
if((ec = curl_easy_perform(curl.get())) != CURLE_OK)
throw std::runtime_error(curl_easy_strerror(ec));
}
return data;
}
int main()
{
curl_global_init(CURL_GLOBAL_DEFAULT);
auto xml = get_url("http://google.co.uk");
std::cout << xml << '\n';
curl_global_cleanup();
}
注意:我还添加了CURLOPT_FOLLOWLOCATION
选项,以防文档上有重定向。
推荐阅读
- r - ggplot2:删除轴标签的第一个单词
- python - json_normalize 嵌套数据库
- javascript - 如何使用 Knex 更新具有重复值的数据?
- webstorm - 使用 WebStorm 2021 调试 Quasar V2
- javascript - 如何检查我的谷歌同意实施是否有效?(标签管理器,网站)
- iis - 如何为“ApplicationPoolIdentity”设置默认代理?
- c# - 如何在通用 Windows 平台中使用具有多个项目的翻转视图并通过其他按钮进行翻转
- kde - Awesome wm - 大字体和面板大小问题
- angular - 角度 10 的 rtsp 实时视频流
- vba - VBA 通过 LAN 网络移动文件不起作用