Afin d'améliorer les performances de lecture à partir d'un fichier, j'essaie de lire tout le contenu d'un gros fichier (plusieurs Mo) en mémoire, puis d'utiliser un istringstream pour accéder aux informations.
Ma question est, quelle est la meilleure façon de lire ces informations et de les "importer" dans le flux de chaînes? Un problème avec cette approche (voir ci-dessous) est que lors de la création du flux de chaînes, les tampons sont copiés et l'utilisation de la mémoire double.
#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
*/
}
_std::ifstream
_ possède une méthode rdbuf()
, qui renvoie un pointeur vers un filebuf
. Vous pouvez ensuite "pousser" ce filebuf
dans votre stringstream
:
_#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: Comme Martin York le fait remarquer dans les commentaires, ce n'est peut-être pas la solution la plus rapide car le _operator<<
_ de stringstream
lira le fichier fichier caractère par caractère. Vous voudrez peut-être vérifier sa réponse, où il utilise la méthode ifstream
de read
comme vous le faisiez, puis définir le tampon stringstream
pour pointer vers le précédemment alloué Mémoire.
D'ACCORD. Je ne dis pas que ce sera plus rapide que de lire le fichier
Mais c'est une méthode où vous créez le tampon une fois et après que les données sont lues dans le tampon, utilisez-le directement comme source pour le flux de chaînes.
N.B.Il convient de mentionner que std :: ifstream est tamponné. Il lit les données du fichier en morceaux (relativement gros). Les opérations de flux sont effectuées sur le tampon et ne reviennent au fichier pour une autre lecture que lorsque davantage de données sont nécessaires. Donc, avant d'aspirer toutes les données en mémoire, veuillez vérifier qu'il s'agit d'un goulot d'étranglement.
#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.
*/
}
}
Cela me semble une optimisation prématurée. Combien de travail est effectué dans le traitement. En supposant un ordinateur de bureau/serveur moderne et non un système intégré, la copie de quelques Mo de données pendant l'initialisation est assez bon marché, en particulier par rapport à la lecture du fichier sur le disque en premier lieu. Je m'en tenir à ce que vous avez, mesurer le système lorsqu'il est terminé et décider si les gains de performances potentiels en valent la peine. Bien sûr, si la mémoire est serrée, c'est dans une boucle interne, ou un programme qui est souvent appelé (comme une fois par seconde), qui change l'équilibre.
Une autre chose à garder à l'esprit est que les E/S de fichiers seront toujours l'opération la plus lente. La solution de Luc Touraille est correcte, mais il existe d'autres options. La lecture du fichier entier dans la mémoire à la fois sera beaucoup plus rapide que les lectures séparées.