Pregunta

Para mejorar la lectura del rendimiento de un archivo, estoy tratando de leer todo el contenido de un archivo grande (varios MB) en la memoria y luego usar un flujo istring para acceder a la información.

Mi pregunta es, ¿cuál es la mejor manera de leer esta información y " importarla " en la secuencia de la secuencia? Un problema con este enfoque (ver más abajo) es que al crear la secuencia de cadena se copian los búferes y se duplica el uso de memoria.

#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
   */

}
¿Fue útil?

Solución

std::ifstream tiene un método rdbuf(), que devuelve un puntero a filebuf. Entonces puede & Quot; presionar & Quot; esto stringstream en su 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...
    }
}

EDITAR: Como Martin York comenta en los comentarios, esta podría no ser la solución más rápida ya que ifstream 's read leerá el archivo de caracteres por carácter. Es posible que desee verificar su respuesta, donde utiliza el método <=> <=> como solía hacerlo, y luego configurar el búfer <=> para que apunte a la memoria asignada previamente.

Otros consejos

OK. No digo que esto sea más rápido que leer el archivo

Pero este es un método en el que crea el búfer una vez y después de que los datos se leen en el búfer, úselos directamente como fuente de secuencia de cadena.

N.B. Vale la pena mencionar que el std :: ifstream está protegido. Lee datos del archivo en fragmentos (relativamente grandes). Las operaciones de flujo se realizan en el búfer solo volviendo al archivo para otra lectura cuando se necesitan más datos. Entonces, antes de absorber todos los datos en la memoria, verifique que se trata de un cuello de botella.

#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.
         */
    }
}

Esto me parece una optimización prematura. Cuánto trabajo se está haciendo en el procesamiento. Asumiendo un escritorio / servidor moderno, y no un sistema embebido, copiar algunos MB de datos durante la inicialización es bastante barato, especialmente en comparación con leer el archivo del disco en primer lugar. Me quedaría con lo que tiene, mediría el sistema cuando esté completo y decidiría si las posibles ganancias de rendimiento valdrían la pena. Por supuesto, si la memoria es escasa, esto está en un bucle interno, o en un programa que se llama con frecuencia (como una vez por segundo), que cambia el equilibrio.

Otra cosa a tener en cuenta es que la E / S de archivos siempre será la operación más lenta. La solución de Luc Touraille es correcta, pero hay otras opciones. Leer todo el archivo en la memoria a la vez será mucho más rápido que lecturas separadas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top