2012-03-08 10 views
6

ho ricercato online per la maggior parte di oggi ma non sono riuscito a trovare la risposta, quindi mi sto rivolgendo allo stackoverflow per qualche suggerimento.come leggere i file di immagine e memorizzarli in memoria (std :: string) in C++?

In sostanza, ho una libreria C++ che usa arricciatura per eseguire il metodo PUT per caricare un file immagine. ora questa libreria prende una std :: string per i dati. Ho file di immagine (come jpg, gif, png) sul mio disco locale.

Non mi interessa il contenuto del file (come in, non faccio niente con esso oltre a passarlo a questa libreria per il metodo PUT). come posso leggere i file immagine e memorizzarli in std :: string? Cosa succede se il contenuto del file contiene il terminatore NULL?

Ho provato ad aggiungere alcuni codici che ho provato, ma sono nuovo qui e non sono sicuro di come incollare il mio codice qui nel formato corretto. Qualsiasi aiuto sarebbe apprezzato.

+0

Per incollare il codice qui, appena rientro di 4 spazi. Oppure, incolla il tuo codice, selezionalo, quindi premi il pulsante simile a questo: '{}'. Puoi anche posizionare il codice in linea con il tuo testo circondandolo di piccole cose. Penso che siano chiamati back-ticks. Su ogni tastiera che abbia mai usato, è la chiave nell'angolo in alto a sinistra, a sinistra del tasto 1. –

+0

@Benjamin: sul layout di tastiera tedesco, è nell'angolo in alto a destra, a sinistra del tasto backspace. :) Devi anche premere ctrl + alt per ottenerlo ... In ogni caso, "\" è inteso. – Xeo

+5

La libreria che si utilizza realmente desidera i dati binari in una stringa? Sicuro che non sia il nome del file che vuole? Mentre il tipo 'char' è un byte su quasi tutte le piattaforme, usare' std :: string' per memorizzare dati binari mi sembra sbagliato. –

risposta

4

Il metodo più semplice a cui riesco a pensare. Apri il file in modalità binaria, quindi leggi l'intera cosa in un stringstream.

std::ifstream fin("foo.png", std::ios::in | std::ios::binary); 
std::ostringstream oss; 
oss << fin.rdbuf(); 
std::string data(oss.str()); 
+0

questo è quello che ho fatto esattamente. ma non ha funzionato in quanto sembrava aver caricato solo una parte dei dati binari. –

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

Si può leggere i file di immagine per std::string con codice come questo. Regola il parametro per il metodo reserve in modo che sia più grande del 99% delle dimensioni del tuo file. Zero byte (che si chiamano terminatori NULL) vengono trattati correttamente con entrambi ifstream e string.


ho trovato un buon article, dove sono confrontati diversi metodi di caricamento del file binario. Ecco il metodo più veloce da tale articolo:

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

Ed ecco il più breve:

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

Aggiornamento

Qualcosa di simile può essere utilizzata per alimentare il callback funzione (non l'ho provato):

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(); 
} 
+0

ho provato la versione abbreviata sul mio codice ieri ma anche questo non ha funzionato. cercherò di ottenere il mio codice qui oggi in modo da poter ottenere più aiuto su questo. –

2

questo è come la biblioteca effettua chiamate PUT dove 'dati' è stringa passata come contenuto del file

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

ed ecco il frunction callback per 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; 
} 
+0

almeno secondo http://stackoverflow.com/questions/9612121/how-to-read-image-files-and-store-it-in-memorystdstring-in-c/9623954#9623954, la stringa deve essere in grado di memorizzare zero byte. hm. –

+0

Sì, la stringa può memorizzare zero byte. Il bug è nella prima riga del tuo codice: 'data.c_str()'. Qui la stringa a terminazione zero viene passata come puntatore char. E così la stringa viene tagliata dal primo byte zero. O rimuovere il 'c_str()' non necessario, o usare 'stringstream' dal metodo di Benjamin nel callback, o puoi semplicemente aprire' ifstream' e usarlo nel callback (questo approccio offre prestazioni migliori). –

+0

hai ragione. Credo di dover riscrivere la funzione di callback –

Problemi correlati