使用CURL读取HTTP数据到字符串或者文件中

这两天简单研究了下CURL访问网站读取数据的方式,做了简单的实验,思路很简单,就是提供一个URL,然后从URL返回的数据读取出来,显示到控制台,或者存储到文件中。具体的描述以及注意事项,代码的注释中都有写明。

上代码。

// DemoLibcurl.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#define CURL_STATICLIB            // 由于我使用的是CURL静态链接,所以需要定义上这个宏
#include "http://www.cnblogs.com/../include/curl/curl.h"

// 一下三个lib为libcurl.lib所依赖的三个库
#pragma comment(lib, "Wldap32.lib")
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Advapi32.lib")

#ifdef _DEBUG
#pragma comment(lib,"http://www.cnblogs.com/../lib/libcurld.lib")
#else
#pragma comment(lib,"http://www.cnblogs.com/../lib/libcurl.lib")
#endif

#include <iostream>
#include <string>
using namespace std;


// 定义一个break宏
#define BREAK_ON_NOT_EQUAL(compareValue, resultValue) {if((compareValue) != (resultValue))break;}


// 执行输出到标准输出流
bool PerformToStdout(IN CURL* nphEasycurl);

// curl指定格式的回调函数
size_t WriteToString(void *buffer, size_t size, size_t nmemb, void *userp);

size_t WriteToFile(void *buffer, size_t size, size_t nmemb, void *userp);

// 执行输出到字符串
bool PerformToString(IN CURL* nphEasycurl, IN string& rstrBuffer);

// 执行输出到文件
bool PerformToFile(IN CURL* nphEasycurl, IN char* nscFileName, bool nbIsUseCallBackMethod = false);

int _tmain(int argc, _TCHAR* argv[])
{
    // 进行初始化
    CURL* lphEasycurl = curl_easy_init(); 
    do 
    {
        // 初始化失败
        if(NULL == lphEasycurl)
        {
            cout << "Error: Init curl handle failed." << endl;
            break;
        }

        // 获取当前使用的curl库的版本信息
        curl_version_info_data* ldVersionInfo = curl_version_info(CURLVERSION_NOW);
        if(NULL != ldVersionInfo && ldVersionInfo->age > 0)
        {
            //// 判断是否支持所需要的功能
            //if(1 !=  (ldVersionInfo->features & CURL_VERSION_GSSNEGOTIATE))        // 不明白这里要用那个宏去进行判断才表示支持HTTP
            //{
            //    cout << "Error: Current Curl version do`nt support HTTP." << endl;
            //    break;
            //}
        }
        else        // 获取版本信息失败
        {
            cout << "Error: Get version info of Curl failed." << endl;
            break;
        }

        // 设置接受错误信息的缓存,CURL_ERROR_SIZE为curl要求的最小大小
        char lscErrBuffer[CURL_ERROR_SIZE];            
        curl_easy_setopt(lphEasycurl, CURLOPT_ERRORBUFFER, &lscErrBuffer);            // 接受错误描述

        // 设置URL
        curl_easy_setopt(lphEasycurl, CURLOPT_URL, "http://www.cnn.com/"); 

        // 执行
        int liOutputType = 2;                // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~通过更改这个值,来尝试不同的方式
        bool lbIsPerformSuccess = false;
        string lstrDataBuffer;
        switch(liOutputType)
        {
        case 1:                // 输出到字符串
            {
                lbIsPerformSuccess = PerformToString(lphEasycurl, lstrDataBuffer);
            }
            break;

        case 2:                // 输出到文件
            {
                lbIsPerformSuccess = PerformToFile(lphEasycurl, "output.txt", true);        // ~~~~~~~~~更改第三个参数来调用不同的实现方式
            }
            break;

        default:            // 输出到标准输出
            {
                lbIsPerformSuccess = PerformToStdout(lphEasycurl);
            }
            break;
        }
        
        // 执行失败,输出错误描述
        if(false == lbIsPerformSuccess)
        {
            cout << "Error: " << lscErrBuffer << endl;
            break;
        }

        // 根据设置的类型进行输出
        if(1 == liOutputType)
        {
            cout  << "The data read from url:" << lstrDataBuffer.c_str() << endl;
        }
        else if(2 == liOutputType)
        {
            cout << "Success: The data have saved to output.txt" << endl;
        }


    } while (false);

    // 清空初始化数据
    if(NULL != lphEasycurl)
        curl_easy_cleanup(lphEasycurl); 

    cout<<endl<<"Press anykey to continue!"<<endl;
    getchar();
    return 0;
}





bool PerformToStdout(IN CURL* nphEasycurl)
{
    bool lbResult = false;
    do 
    {

        if(CURLE_OK != curl_easy_perform(nphEasycurl))
            break;

        lbResult = true;
    } while (false);

    return lbResult;
}




// 功能:
//        libcurl写数据所使用的标准回调函数格式
// 参数:
//        buffer所指向数据块的字节数为size * nmemb,注意不会以0结尾。
//        userp是通过设置CURLOPT_WRITEDATA属性传进来的指针
// 返回值:
//        通常作为实际处理的字节数,如果处理的总字节数和传入的字节总数不同,curl将中止操作并返回错误码CURLE_WRITE_ERROR
size_t WriteToString(void *buffer, size_t size, size_t nmemb, void *userp)
{
    *((std::string*)userp) += (char*)buffer;        // 不是说不是以0结尾的吗?这里用这种方式不会访问越界么?

    return size * nmemb;
}

bool PerformToString(IN CURL* nphEasycurl, IN string& rstrBuffer)
{
    bool lbResult = false;
    do 
    {
        curl_easy_setopt(nphEasycurl, CURLOPT_WRITEFUNCTION, WriteToString);    // 如果不提供这个回调函数,curl将会将数据输出到stdout中。
        curl_easy_setopt(nphEasycurl, CURLOPT_WRITEDATA, &rstrBuffer);
        
        if(CURLE_OK != curl_easy_perform(nphEasycurl))
            break;

        lbResult = true;
    } while (false);

    return lbResult;
}

// 同WriteToString
size_t WriteToFile(void *buffer, size_t size, size_t nmemb, void *userp)
{
    FILE* lphFile = (FILE*)userp;
    if(NULL != lphFile)
    {
        fwrite(buffer, size, nmemb, lphFile);
    }

    return size * nmemb;
}

bool PerformToFile(IN CURL* nphEasycurl, IN char* nscFileName, bool nbIsUseCallBackMethod)
{
    bool lbResult = false;
    FILE* lphFile = NULL;                // CURL要求必须使用FILE
    do 
    {
        if(NULL == nscFileName)
            break;

        // 打开文件
        lphFile = fopen(nscFileName, "wb+");
        if(NULL == lphFile)
        {
            cout << "file open failed." << endl;
            break;
        }
        
        if(false != nbIsUseCallBackMethod)            // 使用回调方式
        {
            // 方式1,将File*传递给回调函数,自己进行处理。
            BREAK_ON_NOT_EQUAL(CURLE_OK, curl_easy_setopt(nphEasycurl, CURLOPT_WRITEFUNCTION, WriteToFile));
        }

        // 方式2,直接将FILE*传递给CURL去进行处理,!注意,CURL默认会使用fwrite写入数据,这也是为什么并且只能传入FILE*的原因。
        BREAK_ON_NOT_EQUAL(CURLE_OK, curl_easy_setopt(nphEasycurl, CURLOPT_WRITEDATA, lphFile));

        // 方式3,用PerformToFile,然后将返回的数据写入File中,这里不进行实验

        // 执行
        BREAK_ON_NOT_EQUAL(CURLE_OK, curl_easy_perform(nphEasycurl));

        lbResult = true;
    } while (false);

    if(NULL != lphFile)
        fclose(lphFile);

    return lbResult;
}

转载于:https://www.cnblogs.com/monotone/archive/2012/11/15/2772140.html

使用curl读取x-mixed-replace格式的视频流,可以按照以下步骤进行: 1. 使用curl库初始化一个curl对象,并设置相关参数,包括URL、请求头、响应头等。 2. 在curl对象注册一个回调函数,用于处理从服务器返回的数据。当数据到达时,curl会调用该回调函数,并将数据传递给它。 3. 在回调函数,处理x-mixed-replace格式的数据。这种格式的数据由多个部分组成,每个部分之间由分隔符分隔。可以使用字符串分割函数或正则表达式来分离每个部分,并对每个部分进行处理。 4. 如果数据是视频流,可以使用视频库(如OpenCV)来处理视频数据,并将视频数据渲染到屏幕上。 下面是一个简单的示例代码,演示如何使用curl和OpenCV读取并显示x-mixed-replace格式的视频流: ```cpp #include <curl/curl.h> #include <opencv2/opencv.hpp> using namespace cv; size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) { Mat *img = (Mat *)stream; vector<uchar> buf(size * nmemb); memcpy(&buf[0], ptr, buf.size()); *img = imdecode(buf, IMREAD_COLOR); return size * nmemb; } int main() { CURL *curl; CURLcode res; Mat frame; Size frameSize(640, 480); curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/video"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &frame); while (true) { res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); break; } if (!frame.empty()) { resize(frame, frame, frameSize); imshow("Video", frame); waitKey(1); } } curl_easy_cleanup(curl); } return 0; } ``` 在上面的示例代码,我们定义了一个回调函数`write_data`,该函数将从服务器接收到的数据解码成一帧视频,并将该帧视频存储在Mat对象`frame`。在主程序,我们使用curl库从服务器读取视频数据,并将每帧视频渲染到屏幕上。如果不需要显示视频,可以省略相关代码。同时,我们还使用了OpenCV来处理视频数据,并将视频数据渲染到屏幕上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值