我编写了这个类,它下载图像,其URL是从本地.txt文件中读取的。我很想确保我的代码是安全和高效的。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include<cassert>
#include <algorithm>
#include <numeric>
#include <functional>
#include <curl/curl.h>
class DownloadTesting
{
private:
CURL *curl;
FILE *file;
CURLcode response;
char outfilename[FILENAME_MAX];
int count {0};
std::vector<char*> URLS; //Stores the urls
auto DownloadImage(const char *url) -> void;
auto Convert(const std::string &s) -> char*;
auto ReadDataStore() -> void;
static auto WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) -> size_t;
public:
DownloadTesting();
~DownloadTesting();
auto Interface() -> void;
};
DownloadTesting::DownloadTesting(){};
DownloadTesting::~DownloadTesting()
{
if(!URLS.empty()) //Delete raw pointers
{
std::for_each(URLS.begin(),URLS.end(),[](char* url){delete url;});
}
}
auto DownloadTesting::WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) -> size_t //Write data into file
{
size_t written {fwrite(ptr, size, nmemb, stream)};
return written;
}
auto DownloadTesting::Convert(const std::string &s) -> char* //Convert url from std::string to raw char pointer
{
char *pc {new char[s.size()+1]};
std::strcpy(pc,s.c_str());
return pc;
}
auto DownloadTesting::ReadDataStore() -> void
{
std::vector<std::string> storage_vector;
std::string storage_string;
std::ifstream storage_file {"./imagestore/urlstore.txt"};
if(storage_file.is_open()) //Open local file
{
while(getline (storage_file,storage_string)) //Read each line
{
storage_vector.push_back(storage_string); //Storage each line in vector
}
storage_file.close();
}
std::transform(storage_vector.begin(), storage_vector.end(), std::back_inserter(URLS), [this](const std::string url){return this->Convert(url);}); //Perform conversion function on each url
}
auto DownloadTesting::DownloadImage(const char *url) -> void
{
count++; //Use a counter to name each downloaded file
std::string name {std::to_string(count)}; //Convert int to string
strcpy(outfilename, name.c_str()); //Convert std::string to [char]
curl = curl_easy_init(); //Initialise curl
if(curl)
{
file = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &DownloadTesting::WriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
response = curl_easy_perform(curl);
curl_easy_cleanup(curl); //Clean up curl
fclose(file); //Close file
}
}
auto DownloadTesting::Interface() -> void
{
this -> ReadDataStore(); //Read in the data
assert(!URLS.empty()); //Ensure data is not empty
std::for_each(URLS.begin(),URLS.end(), [this](const char* url){return this -> DownloadImage(url);}); //Perform download for each url
}
int main()
{
DownloadTesting DTO;
DTO.Interface();
}发布于 2016-12-21 22:09:21
您正在尝试使用新的C++语言特性,但您似乎没有有效地使用它们。
auto用于方法声明以指定行尾的返回类型是令人费解的。规则5:需要自定义析构函数来处理资源(De)分配的类,很可能还需要自定义复制构造函数、赋值操作符和移动构造函数/赋值运算符。
创建字符串的原始副本只是为了存储指向字符的原始指针。当您需要将原始指针传递到库并让string类管理内存时,只需使用string.c_str()。
通过回调将数据写入文件,并要求curl将数据写入文件,这看起来像是重复的工作。有什么原因吗?
这个类不是面向对象设计的好例子。唯一可用的公共方法Interface并不表示它可能会做什么。作为一个函数,整个代码可能会更好。
https://codereview.stackexchange.com/questions/150537
复制相似问题