i've researched online for most of today but could not find the answer so i'm turning to stackoverflow for some suggestion.
basically, i have a c++ library that uses curl to perform PUT method to upload an image file. now this library takes a std::string for data. i have image files (like jpg, gif, png) on my local disk.
i don't care about contents of the file (as in, i don't do anything with it besides passing it to this library for PUT method). how can i read image files and store it in std::string? what if the file content contains NULL terminator?
i tried to add some of codes i've tried, but i'm new here and i'm not sure how to paste my code here in the right format. any help would be appreciated.
Easiest method I can think of. Open the file in binary mode, then read the whole thing into a stringstream
.
std::ifstream fin("foo.png", std::ios::in | std::ios::binary);
std::ostringstream oss;
oss << fin.rdbuf();
std::string data(oss.str());
std::ifstream fin("foo.png", std::ios::binary);
std::string data;
data.reserve(1000000);
std::copy(std::istreambuf_iterator<char>(fin),
std::istreambuf_iterator<char>(),
std::back_inserter(data));
You can read image files to std::string
with code like this. Adjust parameter for reserve
method to be larger than 99% of your file sizes. Zero bytes (which you call NULL terminators) are treated correctly with both ifstream
and string
.
I've found a good article, where several methods of binary file loading are compared. Here is the fastest method from that article:
std::ifstream fin("foo.png", std::ios::binary);
fin.seekg(0, std::ios::end);
std::string data;
data.resize(fin.tellg());
fin.seekg(0, std::ios::beg);
fin.read(&data[0], data.size());
And here is the shortest one:
std::ifstream fin("foo.png", std::ios::binary);
std::string data((std::istreambuf_iterator<char>(fin)),
std::istreambuf_iterator<char>());
Update
Something like this may be used to feed the callback function (I didn't test it):
std::ifstream fin("foo.png", std::ios::binary);
fin.seekg(0, std::ios::end);
...
curl_easy_setopt(m_ctx, CURLOPT_INFILESIZE, fin.tellg());
curl_easy_setopt(m_ctx, CURLOPT_READDATA, (void *)&fin);
fin.seekg(0, std::ios::beg);
...
static size_t put_callback(void *ptr, size_t size, size_t nmemb, void *data){
std::ifstream* in = static_cast<std::ifstream*>(data);
if(in->eof()) return 0;
in->read((char *)ptr, size*nmemb);
return in->gcount();
}
this is how the library makes PUT calls where 'data' is string passed in as file content
stringstream data_stream.str(data.c_str());
curl_easy_setopt(m_ctx, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(m_ctx, CURLOPT_PUT, 1L);
curl_easy_setopt(m_ctx, CURLOPT_INFILESIZE, data.length());
curl_easy_setopt(m_ctx, CURLOPT_READFUNCTION, put_callback);
curl_easy_setopt(m_ctx, CURLOPT_READDATA, (void *)&data_stream);
curl_easy_setopt(m_ctx, CURLOPT_WRITEFUNCTION, get_callback);
curl_easy_setopt(m_ctx, CURLOPT_WRITEDATA, (void *)&m_request_response);
and here is the callback frunction for curlopt_readfunction
static size_t put_callback(void *ptr, size_t size, size_t nmemb, void *data){
stringstream *output_stream;
int retval;
output_stream = (stringstream *) data;
if(output_stream->eof()) return 0;
retval = min(size*nmemb,output_stream->str().size());
output_stream->read((char *)ptr, retval);
//return the number of bytes processed
return retval;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With