¿Cómo leer el contenido del archivo en istringstream?

Para mejorar la lectura de rendimiento de un archivo, bash leer todo el contenido de un gran archivo (varios MB) en la memoria y luego utilizar un istringstream para acceder a la información.

Mi pregunta es, ¿cuál es la mejor manera de leer esta información e “importarla” en el flujo de cadenas? Un problema con este enfoque (ver a continuación) es que al crear la secuencia de cadenas, los búferes se copian y el uso de la memoria se duplica.

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

std::ifstream tiene un método rdbuf() , que devuelve un puntero a un filebuf . A continuación, puede “insertar” este filebuf en su stringstream :

 int main() { std::ifstream file( "myFile" ); if ( file ) { std::stringstream buffer; buffer < < file.rdbuf(); file.close(); // operations on the buffer... } } 

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

DE ACUERDO. No digo que esto sea más rápido que leer desde 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, utilícelos directamente como origen de la secuencia de cadenas.

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

 #include  #include  #include  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 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 integrado, copiar unos pocos MB de datos durante la inicialización es bastante barato, especialmente en comparación con leer el archivo fuera del disco en primer lugar. Me quedaría con lo que tienes, mediré el sistema cuando esté completo y decidiré si las posibles mejoras de rendimiento valdrían la pena. Por supuesto, si la memoria es escasa, se trata de un bucle interno, o de un progtwig al 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 archivo 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 de una vez será mucho más rápido que las lecturas por separado.