2013-03-27 12 views
20

Ich bin auf der Suche nach einer Klärung, wie seekg() und seekp() in Bezug auf arbeitet, wenn Sie in eine Datei schreiben. Sagen Sie zum Beispiel habe ich eine Datei in etwa so:fstream seekg(), seekp() und write()

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

Jetzt mag ich die Datei öffnen und einige suchen Werte lesen und zu schreiben.

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 

Jetzt möchte ich an das Ende der Datei schreiben. Da die seekg() Funktion nur den Suchcursor bewegt, sollte mein seekp() Cursor immer noch am Ende der Datei rechts sein? Also:

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

sollte meine Datei machen nun wie folgt aussehen:

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

Nun, was zu meiner Datei passiert, wenn ich auf einen Versatz suchen, auswählen und seinen Wert schreiben, wie die auf den Offset-Wert, der war gerade eingefügt. Zum Beispiel möchte ich offset 8eofOffset = 20 halten, da wir gerade 12 bei diesem Offset eingefügt haben.

Wenn ich tun:

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

macht es umschreiben richtig meine Datei wie folgt aussehen:

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

Bitte lassen Sie mich wissen, wenn ich Fehler mache die seekg() und seekp() Funktionen.

Antwort

21

Die Klassenschablone std::basic_filebuf hält eine einzelne Datei Position

§ 27.9.1.1

  1. Die Klasse basic_filebuf assoziiert sowohl die Eingang Sequenz und die Ausgangssequenz mit einem Datei.
  2. Die Einschränkungen für das Lesen und Schreiben einer Sequenz, die von einem Objekt der Klasse basic_filebuf gesteuert wird, sind dieselben wie für Lesen und Schreiben mit der Standard C-Bibliothek FILEs.
  3. Insbesondere:
    • Wenn die Datei zum Lesen der Eingangssequenz nicht geöffnet ist nicht gelesen werden kann.
    • Wenn die Datei nicht zum Schreiben geöffnet ist, kann die Ausgabesequenz nicht geschrieben werden.
    • Eine gemeinsame Dateiposition wird sowohl für die Eingabesequenz als auch für die Ausgabesequenz beibehalten.

Was dies bedeutet, ist, dass, wenn Sie ein std::basic_fstream verwenden, die standardmäßig ein std::basic_filebuf verwendet, die einzelne Datei Position sowohl von seekp() und seekg() bewegt wird; es sei denn, Sie verwenden eine separate Variable, um eine der Positionen zu speichern, so dass Sie dann zurück suchen können, können Sie nicht verfolgen, Put und Positionen unabhängig zu bekommen.Die Auswirkungen von Punkt 2 sind, dass zwischen Lesen und Schreiben auf eine fstream Sie müssen entweder den Puffer leeren oder suchen Sie die Dateiposition beim Wechsel von Ausgabe zu Eingabe, und Sie müssen entweder am Ende der Datei sein oder suchen Sie die Dateiposition beim Wechsel von Eingang zu Ausgang.

Einzelheiten zu diesen Einschränkungen finden Sie in Abschnitt 7.19.5.3/7 der C99-Norm ("Die -Funktion") oder in 7.21.5.3/7 von C11.

+0

Danke! Wann würden Sie also den Puffer spülen? Würden Sie es nach jedem Lesen und Schreiben leeren, oder wäre es in Ordnung, es zu verlassen, wie es ist, wenn Sie eine Reihe von Lesevorgängen oder eine Reihe von Schreibvorgängen machen? – raphnguyen

+1

@raphnguyen Spülen des Puffers ist eine relativ teure Operation, es gibt normalerweise keine Notwendigkeit, manuell zu spülen, es sei denn, Sie wechseln vom Schreiben zum Lesen und Sie suchen nicht, es sei denn, Sie haben einen guten Grund zu spülen lassen die Implementierung mit anderen Spülung. – user657267

Verwandte Themen