Domanda

Per migliorare la lettura delle prestazioni da un file, sto cercando di leggere l'intero contenuto di un file di grandi dimensioni (diversi MB) in memoria e quindi utilizzare un istringstream per accedere alle informazioni.

La mia domanda è: qual è il modo migliore per leggere queste informazioni e " importale " nel flusso di stringhe? Un problema con questo approccio (vedi sotto) è che quando si crea il flusso di stringhe i buffer vengono copiati e l'utilizzo della memoria raddoppia.

#include <fstream>
#include <sstream>

using namespace std;

int main() {
  ifstream is;
  is.open (sFilename.c_str(), ios::binary );

  // get length of file:
  is.seekg (0, std::ios::end);
  long length = is.tellg();
  is.seekg (0, std::ios::beg);

  // allocate memory:
  char *buffer = new char [length];

  // read data as a block:
  is.read (buffer,length);

  // create string stream of memory contents
  // NOTE: this ends up copying the buffer!!!
  istringstream iss( string( buffer ) );

  // delete temporary buffer
  delete [] buffer;

  // close filestream
  is.close();

  /* ==================================
   * Use iss to access data
   */

}
È stato utile?

Soluzione

std::ifstream ha un metodo rdbuf(), che restituisce un puntatore a filebuf. È quindi possibile & Quot; premere & Quot; questo stringstream nel tuo operator<<:

#include <fstream>
#include <sstream>

int main()
{
    std::ifstream file( "myFile" );

    if ( file )
    {
        std::stringstream buffer;

        buffer << file.rdbuf();

        file.close();

        // operations on the buffer...
    }
}

EDIT: come osserva Martin York nei commenti, questa potrebbe non essere la soluzione più veloce poiché i ifstream read leggeranno il filebuf carattere per carattere. Potresti voler controllare la sua risposta, dove usa il metodo <=> <=> come una volta, e quindi impostare il <=> buffer in modo che punti alla memoria allocata in precedenza.

Altri suggerimenti

OK. Non sto dicendo che questo sarà più veloce della lettura dal file

Ma questo è un metodo in cui si crea il buffer una volta e dopo che i dati sono stati letti nel buffer, lo si utilizza direttamente come sorgente per stringstream.

N.B. Vale la pena ricordare che lo std :: ifstream è bufferizzato. Legge i dati dal file in blocchi (relativamente grandi). Le operazioni di streaming vengono eseguite sul buffer solo ritornando al file per un'altra lettura quando sono necessari più dati. Quindi, prima di risucchiare tutti i dati in memoria, verifica che si tratti di un collo di bottiglia.

#include <fstream>
#include <sstream>
#include <vector>

int main()
{
    std::ifstream       file("Plop");
    if (file)
    {
        /*
         * Get the size of the file
         */
        file.seekg(0,std::ios::end);
        std::streampos          length = file.tellg();
        file.seekg(0,std::ios::beg);

        /*
         * Use a vector as the buffer.
         * It is exception safe and will be tidied up correctly.
         * This constructor creates a buffer of the correct length.
         *
         * Then read the whole file into the buffer.
         */
        std::vector<char>       buffer(length);
        file.read(&buffer[0],length);

        /*
         * Create your string stream.
         * Get the stringbuffer from the stream and set the vector as it source.
         */
        std::stringstream       localStream;
        localStream.rdbuf()->pubsetbuf(&buffer[0],length);

        /*
         * Note the buffer is NOT copied, if it goes out of scope
         * the stream will be reading from released memory.
         */
    }
}

Mi sembra un'ottimizzazione prematura. Quanto lavoro viene svolto nell'elaborazione. Supponendo un desktop / server modernista, e non un sistema incorporato, la copia di alcuni MB di dati durante l'inizializzazione è piuttosto economica, soprattutto rispetto alla lettura del file dal disco in primo luogo. Vorrei attenermi a quello che hai, misurare il sistema quando è completo e deciderei se valgono la pena i potenziali guadagni in termini di prestazioni. Naturalmente se la memoria è stretta, questo è in un ciclo interno, o in un programma che viene chiamato spesso (come una volta al secondo), che cambia l'equilibrio.

Un'altra cosa da tenere a mente è che l'I / O dei file sarà sempre l'operazione più lenta. La soluzione di Luc Touraille è corretta, ma ci sono altre opzioni. Leggere l'intero file in memoria contemporaneamente sarà molto più veloce delle letture separate.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top