创建一个C ++类,使用libcurl将网站中的数据读取到字符串

时间:2014-02-27 22:31:57

标签: c++ libcurl

我使用http://ubuntuforums.org/showthread.php?t=781021作为如何编写c ++程序的指南,该程序使用libcurl检查网站并将文本下载到c ++应用程序。当我将代码复制到我的visual studio项目时,它只需稍加修改即可使用。但是,我试图将其转换为基于类的文件。

我创建了.h.cpp个文件来运行查询。我之前没有意识到的是handle_data不是一个典型的函数,因为它在Viewer.cpp的中途没有给出任何参数甚至()。这就是上面的网站如何做到的,并且它有效,但我现在还不知道为什么或如何转换它。

有谁知道这里发生了什么或如何修复它? 谢谢!

Viewer.h:

#pragma once

#include <string>
#include "curl.h"

class Viewer
{
public:
    Viewer(void);
    ~Viewer(void);

    std::string view(std::string q);

private:
    size_t handle_data(void *ptr, size_t size, size_t nmemb, void *stream);

    std::string contents;

};

Viewer.cpp:

#include "stdafx.h"
#include "Viewer.h"
#include <iostream>

Viewer::Viewer(void)
{
std::cout << "ViewerCreated!\n";
}


Viewer::~Viewer(void)
{
}

size_t Viewer::handle_data(void *ptr, size_t size, size_t nmemb, void *stream) 
{ 
    int numbytes = size*nmemb; 
    // The data is not null-terminated, so get the last character, and replace 
    // it with '\0'. 
    char lastchar = *((char *) ptr + numbytes - 1); 
    *((char *) ptr + numbytes - 1) = '\0'; 
    contents.append((char *)ptr); 
    contents.append(1,lastchar); 
    *((char *) ptr + numbytes - 1) = lastchar;  // Might not be necessary. 
    return size*nmemb; 
}

std::string Viewer::view(std::string q)
{
    char* url = "www.google.com";

    CURL* curl = curl_easy_init(); 
    if(curl) 
        { 
        // Tell libcurl the URL 
        curl_easy_setopt(curl,CURLOPT_URL, url); 
        // Tell libcurl what function to call when it has data 
        curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,handle_data); 
        // Do it! 
        CURLcode res = curl_easy_perform(curl); 
        curl_easy_cleanup(curl); 
        if (res == 0) 
            std::cout << contents << std::endl; 
        else 
            std::cerr << "Error: " << res << std::endl; 
        } 

    return contents;
}

3 个答案:

答案 0 :(得分:1)

您不应该替换您收到的块的最后一个字符。相反,您应该强制包含附加块的缓冲区在数据结束后才有'\ 0'。这种方式可以打印,但是如果要将其存储在文件中,则应该只写下你收到的字节。

这一直对我有用:

struct MemoryStruct chunk;
chunk.memory=NULL;
chunk.size = 0; 
...
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

回调:

struct MemoryStruct {
   char *memory;
   size_t size;
};

static void *myrealloc(void *ptr, size_t size)
{
   if(ptr)
      return realloc(ptr, size);
    else
      return malloc(size);
 }

static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
   size_t realsize = size * nmemb;
   struct MemoryStruct *mem = (struct MemoryStruct *)data;
   mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
   if (mem->memory) {
      memcpy(&(mem->memory[mem->size]), ptr, realsize);
      mem->size += realsize;
      mem->memory[mem->size] = 0;
   }
   return realsize;
}

答案 1 :(得分:0)

handle_data用作curl_easy_setopt的参数。这意味着你必须编写handle_data在接收下一个数据块时所做的事情(假设数据块是curl将为你做的事情)。

答案 2 :(得分:0)

handle_data作为回调函数传递给curl_easy_setopt,当有可用数据时,它将调用它。因此,handle_data必须被称为静态函数(即,没有接收到对象指针,因为cURL没有一个)。但是,您并未将其声明为静态。即使您这样做,也会访问其中的contents,这是无效的。