Comment lire un gros fichier en c ++

Si j’ai un fichier énorme (par exemple, 1 To, ou une taille qui ne rentre pas dans la RAM. Le fichier est stocké sur le disque). Il est délimité par l’espace. Et ma RAM ne fait que 8 Go. Puis-je lire ce fichier en ifstream? Sinon, comment lire un bloc de fichier (4 Go, par exemple)?

Il y a plusieurs choses que vous pouvez faire.

Premièrement, il n’ya aucun problème à ouvrir un fichier plus volumineux que la quantité de RAM dont vous disposez. Ce que vous ne pourrez pas faire est de copier le fichier entier en direct dans votre mémoire. La meilleure chose à faire serait que vous trouviez un moyen de lire quelques morceaux à la fois et de les traiter. Vous pouvez utiliser ifstream à cette fin (avec ifstream.read , par exemple). Allouez, disons, un mégaoctet de mémoire, lisez le premier mégaoctet de ce fichier, rincez et répétez:

 ifstream bigFile("mybigfile.dat"); constexpr size_t bufferSize = 1024 * 1024; unique_ptr buffer(new char[bufferSize]); while (bigFile) { bigFile.read(buffer.get(), bufferSize); // process data in buffer } 

Une autre solution consiste à mapper le fichier en mémoire. La plupart des systèmes d’exploitation vous permettent de mapper un fichier sur la mémoire même s’il est plus grand que la quantité de mémoire physique dont vous disposez. Cela fonctionne car le système d’exploitation sait que chaque page de mémoire associée au fichier peut être mappée et désaffectée à la demande: lorsque votre programme a besoin d’une page spécifique, le système d’exploitation le lit à partir du fichier dans la mémoire de votre processus et échange une page qui n’a pas été utilisé depuis un moment.

Toutefois, cela ne peut fonctionner que si le fichier est plus petit que la quantité maximale de mémoire que votre processus peut théoriquement utiliser. Ce n’est pas un problème avec un fichier de 1 To dans un processus 64 bits, mais cela ne fonctionnerait pas dans un processus 32 bits.

Soyez également conscient des esprits que vous invoquez . Le mappage de la mémoire d’un fichier n’est pas la même chose que la lecture de celui-ci. Si le fichier est soudainement tronqué à partir d’un autre programme, votre programme risque de se bloquer. Si vous modifiez les données, il est possible que vous manquiez de mémoire si vous ne pouvez pas sauvegarder sur le disque. En outre, l’algorithme de votre système d’exploitation pour la mémorisation d’entrée et de sortie de la mémoire peut ne pas vous être très avantageux. En raison de ces incertitudes, je n’envisagerais de mapper le fichier que si sa lecture par fragments en utilisant la première solution ne peut pas fonctionner.

Sous Linux / OS X, vous utiliseriez mmap pour cela. Sous Windows, vous ouvrez un fichier, puis utilisez CreateFileMapping puis MapViewOfFile .

Je suis sûr que vous ne devez pas garder tout le fichier en mémoire. Généralement, on veut lire et traiter des fichiers par morceaux. Si vous voulez utiliser ifstream , vous pouvez faire quelque chose comme ça:

 ifstream is("/path/to/file"); char buf[4096]; do { is.read(buf, sizeof(buf)); process_chunk(buf, is.gcount()); } while(is); 

Une approche plus avancée consiste à mapper la mémoire au lieu de lire le fichier entier ou ses fragments en mémoire en utilisant un apis spécifique à la plate-forme:

Sous Windows: CreateFileMapping (), MapViewOfFile ()

Sous linux: open (2) / creat (2), shm_open, mmap

vous aurez besoin de comstackr l’application 64bit pour le faire fonctionner.

pour plus de détails, voir ici: CreateFileMapping, MapViewOfFile, comment éviter de bloquer la mémoire système

Vous pouvez utiliser fread

 char buffer[size]; fread(buffer, size, sizeof(char), fp); 

Ou, si vous voulez utiliser les stream C ++, vous pouvez utiliser read comme le dit buratino .

Sachez également que vous pouvez ouvrir un fichier quelle que soit sa taille, l’idée est de l’ouvrir et de le lire dans des mandrins qui correspondent à votre RAM.