Question

Afin d’améliorer les performances de lecture d’un fichier, j’essaie de lire le contenu complet d’un fichier volumineux (plusieurs Mo) en mémoire, puis d’utiliser un flux istring pour accéder aux informations.

Ma question est la suivante: quel est le meilleur moyen de lire ces informations et & "Importez-les &"; dans le flux de chaîne? Un problème avec cette approche (voir ci-dessous) est que, lors de la création du flux de chaîne, les tampons sont copiés et la mémoire utilisée doublée.

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

}
Était-ce utile?

La solution

std::ifstream a une méthode rdbuf() qui renvoie un pointeur sur un filebuf. Vous pouvez alors & Quot; pousser & Quot; ceci stringstream dans votre 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: Comme le remarque Martin York dans les commentaires, il ne s’agit peut-être pas de la solution la plus rapide, car les ifstream read lisent fichier par fichier. Vous voudrez peut-être vérifier sa réponse, où il utilise la méthode <=> du <=> comme vous le faisiez, puis configurez le tampon <=> pour qu'il pointe vers la mémoire allouée précédemment.

Autres conseils

OK Je ne dis pas que ce sera plus rapide que de lire le fichier

Mais c’est une méthode dans laquelle vous créez le tampon une fois, puis, une fois les données lues dans le tampon, vous l’utilisez directement comme source du flux de chaîne.

N.B. Il est à noter que le std :: ifstream est mis en mémoire tampon. Il lit les données du fichier par morceaux (relativement volumineux). Les opérations de flux sont effectuées sur la mémoire tampon qui retourne dans le fichier uniquement pour une nouvelle lecture lorsque davantage de données sont nécessaires. Donc, avant de sucer toutes les données en mémoire, vérifiez qu'il s'agit bien 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 fait dans le traitement. En supposant un poste de travail / serveur moderne, et non un système embarqué, la copie de quelques Mo de données lors de l’initialisation est relativement peu coûteuse, surtout par rapport à la lecture du fichier sur disque. Je m'en tiendrai à ce que vous avez, mesurer le système quand il est terminé et décider si les gains de performances potentiels en valent la peine. Bien sûr, si la mémoire est saturée, il s’agit d’une boucle interne ou d’un programme appelé souvent (par exemple, une fois par seconde) qui modifie l’équilibre.

Une autre chose à garder à l’esprit est que l’entrée / la sortie de fichier sera toujours l’opération la plus lente. La solution de Luc Touraille est correcte, mais il existe d'autres options. Lire tout le fichier en mémoire à la fois sera beaucoup plus rapide que des lectures séparées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top