web-dev-qa-db-fra.com

fstream rechercheg (), recherchep () et écriture ()

Je cherche des éclaircissements sur la façon dont seekg() et seekp() fonctionne quand vous écrivez dans un fichier. Disons par exemple que j'avais un fichier comme ça:

offset 0: 2
offset 4: 4
offset 8: 6
offset 12: 8
offset 16: 10

Maintenant, je veux ouvrir le fichier et faire quelques recherches pour lire et écrire des valeurs.

fstream file;
file.open("file.txt", fstream::in |fstream::out | fstream::binary);
file.seekp(0, ios::end) // seek to the end of the file
int eofOffset = file.tellp(); // store the offset of the end-of-file, in this case 20

int key = 0;

file.seekg(12, ios::beg); // set the seek cursor to offset 12 from the beginning of the file
file.read((char *) &key, (int)sizeof(int)); // read in the next 4 bytes and assign it to key, in this case 8
file.seekg(8, ios::beg); // set the seek cursor to offset 8 from the beginning of the file
file.read((char *) &key, (int)sizeof(int)); // read in the next 4 bytes and assign it to key, in this case 6

Maintenant, je veux écrire à la fin du fichier. Étant donné que la fonction seekg() déplace uniquement le curseur de recherche, mon curseur seekp() doit toujours être à la fin du fichier, n'est-ce pas? Alors:

int newKey = 12;
file.write((char *) &newKey, sizeof(int));

devrait faire ressembler mon fichier:

offset 0: 2
offset 4: 4
offset 8: 6
offset 12: 8
offset 16: 10
offset 20: 12

Maintenant, qu'arrive-t-il à mon fichier si je choisis de rechercher un décalage et d'écrire sa valeur comme décalage dans la valeur qui vient d'être insérée. Par exemple, je veux que offset 8 Contienne eofOffset = 20 Puisque nous venons d'insérer 12 à ce décalage.

Si je fais:

file.seekp(8, ios::beg);
file.write((char *) &eofOffset, sizeof(int));

réécrit-il correctement mon fichier pour ressembler à ceci:

offset 0: 2
offset 4: 4
offset 8: 20
offset 12: 8
offset 16: 10
offset 20: 12

Veuillez me faire savoir si je fais des erreurs en utilisant les fonctions seekg() et seekp().

21
raphnguyen

Le modèle de classe std::basic_filebuf Contient une seule position de fichier

§ 27.9.1.1

  1. La classe basic_filebuf associe à la fois la séquence d'entrée et la séquence de sortie à un fichier.
  2. Les restrictions sur la lecture et l'écriture d'une séquence contrôlée par un objet de classe basic_filebuf sont les mêmes que pour la lecture et l'écriture avec les FICHIERS de la bibliothèque C standard.
  3. En particulier:
    • Si le fichier n'est pas ouvert pour la lecture, la séquence d'entrée ne peut pas être lue.
    • Si le fichier n'est pas ouvert pour l'écriture, la séquence de sortie ne peut pas être écrite.
    • ne position de fichier commune est conservée pour la séquence d'entrée et la séquence de sortie.

Cela signifie que lorsque vous utilisez un std::basic_fstream, Qui par défaut utilise un std::basic_filebuf, La position du fichier unique est déplacée par les deux seekp() et seekg(); à moins que vous n'utilisiez une variable distincte pour stocker l'une des positions afin que vous puissiez ensuite y revenir, vous ne pouvez pas suivre les positions put et get indépendamment.

Les implications du point 2 sont qu'entre les lectures et les écritures sur un fstream, vous devez soit vider le tampon, soit rechercher la position du fichier lors du passage de la sortie à l'entrée, et vous devez soit être à la fin du fichier, soit rechercher la position du fichier lors du passage de l'entrée à la sortie.

Pour plus de détails sur ces restrictions, voir la section 7.19.5.3/7 de la norme C99 ("La fonction fopen"), ou 7.21.5.3/7 de C11.

22
user657267