You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中将curl获取的数据读取到std::stringstream中?

问题:如何让libcurl直接写入std::stringstream并通过getline处理数据

我在处理Web API,需要读取文本数据做后续处理,数据量最高可达90MB。想把数据直接读到std::stringstream里,之后用std::getline()逐行存入std::string,但没法让curl和stringstream配合工作。

我的代码如下:

#include <iostream> 
#include <sstream> 
#include <string>
#include <curl/curl.h>

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    std::stringstream *stream=(std::stringstream *)userp;
    return realsize;
}

int main(int argc, char* argv[]) { 
    CURL *curl;
    CURLcode res;
    std::stringstream stream;
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "http://date.jsontest.com/"); // simple, small example
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&stream);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
    }
    std::cout << "[" << stream.str() << "]" << std::endl;
    // the loop with getline() would enter here
    return 0;
}

输出结果:

[]

我尝试过这些方法但没解决:

  • 参考过用istream的代码,但编译报错basic_istream is protected within this context
  • 试过在回调里替换成istream,也去掉过(void*)强制转换,但stream始终为空
  • 知道可以用std::string替代,但觉得用getline拆分比自己处理字符串更快;也试过先读入string再转stream,但会复制整个字符串,效率低

编辑补充:常见的curl写入string的回调代码是这样的:

static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

我意识到自己的回调和这个差距很大,但不知道怎么向stringstream追加数据。


解决方法

核心问题是你的WriteMemoryCallback根本没把curl返回的内容写入stringstream,只计算了字节数就返回了。要实现直接写入,调用std::stringstream::write()方法即可,它能直接接收字符指针和字节数,把数据追加到流中。

修改后的回调函数

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    // 用static_cast替代C风格强制转换,更符合C++规范
    std::stringstream *stream = static_cast<std::stringstream*>(userp);
    // 将curl传来的内容写入stringstream
    stream->write(static_cast<char*>(contents), realsize);
    return realsize;
}

完整可运行代码

#include <iostream> 
#include <sstream> 
#include <string>
#include <curl/curl.h>

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    std::stringstream *stream = static_cast<std::stringstream*>(userp);
    stream->write(static_cast<char*>(contents), realsize);
    return realsize;
}

int main(int argc, char* argv[]) { 
    CURL *curl;
    CURLcode res;
    std::stringstream stream;
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "http://date.jsontest.com/");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
    }
    
    // 用getline逐行读取流中数据
    std::string line;
    while (std::getline(stream, line)) {
        std::cout << "读取到行:" << line << std::endl;
    }
    
    return 0;
}

关键说明

  • std::stringstream::write()直接操作流的内部缓冲区,不需要额外复制数据(除非缓冲区扩容,这是流的正常机制,和写入std::string的开销一致)
  • 避免了先写入string再转流的二次复制,符合你对效率的要求
  • 回调必须返回实际处理的字节数,curl会根据这个判断传输是否正常,如果返回值和realsize不一致,curl会中断传输

内容的提问来源于stack exchange,提问作者Rodrigo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:02:15