Как читать файлы изображений и хранить их в памяти (std :: string) в C ++? - PullRequest
7 голосов
/ 08 марта 2012

Я исследовал онлайн большую часть сегодняшнего дня, но не смог найти ответ, поэтому обращаюсь к stackoverflow за некоторыми советами.

В основном, у меня есть библиотека c ++, которая использует curl для выполнения метода PUT для загрузки файла изображения. теперь эта библиотека принимает std :: string для данных. У меня есть файлы изображений (например, JPG, GIF, PNG) на моем локальном диске.

Меня не волнует содержимое файла (как, впрочем, я ничего с ним не делаю, кроме передачи его в эту библиотеку для метода PUT). Как я могу прочитать файлы изображений и сохранить его в std :: string? Что, если содержимое файла содержит терминатор NULL?

Я пытался добавить некоторые коды, которые я пробовал, но я новичок здесь, и я не уверен, как вставить свой код здесь в правильном формате. любая помощь будет оценена.

Ответы [ 3 ]

4 голосов
/ 08 марта 2012

Самый простой метод, который я могу придумать. Откройте файл в двоичном режиме, затем прочитайте все в stringstream.

std::ifstream fin("foo.png", std::ios::in | std::ios::binary);
std::ostringstream oss;
oss << fin.rdbuf();
std::string data(oss.str());
3 голосов
/ 08 марта 2012
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));

Вы можете читать файлы изображений на std::string с таким кодом. Отрегулируйте параметр для метода reserve, чтобы он превышал 99% размера файла. Нулевые байты (которые вы называете NULL-терминаторами) обрабатываются правильно как ifstream, так и string.


Я нашел хорошую статью , в которой сравниваются несколько методов загрузки двоичных файлов. Вот самый быстрый метод из этой статьи:

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());

А вот самый короткий:

std::ifstream fin("foo.png", std::ios::binary);
std::string data((std::istreambuf_iterator<char>(fin)),
                 std::istreambuf_iterator<char>());

Обновление

Нечто подобное можно использовать для подачи функции обратного вызова (я не проверял это):

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();
}
2 голосов
/ 08 марта 2012

это то, как библиотека выполняет PUT-вызовы, где 'data' - строка, передаваемая как содержимое файла

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);

а вот функция обратного вызова для 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...