2010-10-31 13 views
15

Esiste comunque la possibilità di trasferire i dati da un fstream (un file) a uno stringstream (uno stream in memoria)?Copia i dati da fstream a stringstream senza buffer?

Attualmente, sto utilizzando un buffer, ma questo richiede il doppio della memoria, perché è necessario copiare i dati in un buffer, quindi copiare il buffer nello stringstream e finché non si elimina il buffer, i dati vengono duplicati nella memoria.

std::fstream fWrite(fName,std::ios::binary | std::ios::in | std::ios::out); 
    fWrite.seekg(0,std::ios::end); //Seek to the end 
    int fLen = fWrite.tellg(); //Get length of file 
    fWrite.seekg(0,std::ios::beg); //Seek back to beginning 
    char* fileBuffer = new char[fLen]; 
    fWrite.read(fileBuffer,fLen); 
    Write(fileBuffer,fLen); //This writes the buffer to the stringstream 
    delete fileBuffer;` 

Qualcuno sa come posso scrivere un intero file su un stringstream senza utilizzare un buffer intermedio?

+0

Qual è il punto? Stai cercando di migliorare il rendimento? Probabilmente avrete bisogno di abbandonare "fstream" in quel caso, gli iostreams sono SLOW. Stai cercando di ridurre il tuo impatto sulla memoria? La lettura del file in blocchi invece di tutti in una volta potrebbe essere d'aiuto. –

risposta

25
// need to include <algorithm> and <iterator>, and of course <fstream> and <sstream> 
ifstream fin("input.txt"); 
ostringstream sout; 
copy(istreambuf_iterator<char>(fin), 
    istreambuf_iterator<char>(), 
    ostreambuf_iterator<char>(sout)); 
+0

Questo sta ancora leggendo il file nel buffer 'ifstream'. –

+0

È un buffer in meno rispetto al codice originale. –

+0

@Charles - Ciononostante, penso che questo sia ciò che intendeva. Non voleva assegnare un nuovo array di caratteri. Voleva leggere direttamente dall'oggetto fstream all'oggetto stringstream. –

20
ifstream f(fName); 
stringstream s; 
if (f) { 
    s << f.rdbuf();  
    f.close(); 
} 
1

L'unico modo utilizzando la libreria standard C++ è quello di utilizzare un ostrstream invece di stringstream.

È possibile creare un oggetto ostrstream con il proprio buffer di caricamento, che assumerà la proprietà del buffer (quindi non è più necessaria alcuna copia).

Nota tuttavia che l'intestazione strstream è deprecata (sebbene sia ancora parte di C++ 03, e molto probabilmente, sarà sempre disponibile nella maggior parte delle implementazioni di libreria standard) e si verificheranno grossi problemi se si dimentica per terminare con null i dati forniti a ostrstream. Questo vale anche per gli operatori di streaming, ad esempio: ostrstreamobject << some_data << std::ends; (std::ends nullterminate i dati).

7

Nella documentazione per ostream, ci sono several overloads for operator<<. Uno di questi prende uno streambuf* e legge tutto il contenuto dello streambuffer.

Ecco un uso del campione (compilato e testato):

#include <exception> 
#include <iostream> 
#include <fstream> 
#include <sstream> 

int main (int, char **) 
try 
{ 
     // Will hold file contents. 
    std::stringstream contents; 

     // Open the file for the shortest time possible. 
    { std::ifstream file("/path/to/file", std::ios::binary); 

      // Make sure we have something to read. 
     if (!file.is_open()) { 
      throw (std::exception("Could not open file.")); 
     } 

      // Copy contents "as efficiently as possible". 
     contents << file.rdbuf(); 
    } 

     // Do something "useful" with the file contents. 
    std::cout << contents.rdbuf(); 
} 
catch (const std::exception& error) 
{ 
    std::cerr << error.what() << std::endl; 
    return (EXIT_FAILURE); 
} 
Problemi correlati