2013-03-27 28 views
20

Sto cercando alcuni chiarimenti su come seekg() e seekp() funziona rispetto a quando si scrive su un file. Dire per esempio ho avuto un file in questo modo:fstream seekg(), seekp() e write()

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

Ora voglio aprire il file e fare un po 'cerca di leggere e scrivere i valori.

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 

Ora voglio scrivere fino alla fine del file. Poiché la funzione seekg() sposta solo il cursore di ricerca, il mio cursore seekp() dovrebbe essere ancora alla fine del file, giusto? Quindi:

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

dovrebbe rendere il mio file apparire così:

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

Ora che cosa accade al mio file se scelgo di cercare di un offset e scrivere il suo valore come offset per il valore che era appena inserito. Ad esempio, voglio offset 8 per contenere eofOffset = 20 poiché abbiamo appena inserito 12 in tale offset.

Se lo faccio:

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

lo fa correttamente riscrivere il mio file di simile a questa:

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

Si prega di farmi sapere se sto facendo tutti gli errori che utilizzano i seekg() e seekp() funzioni.

risposta

21

Il modello classe std::basic_filebuf detiene un singolo file di posizione

§ 27.9.1.1

  1. Gli associati basic_filebuf classe sia l'ingresso sequenza e la sequenza di uscita con un file.
  2. Le restrizioni sulla lettura e la scrittura di una sequenza controllata da un oggetto di classe basic_filebuf sono le stesse di lettura e scrittura con la libreria C standard FILE.
  3. In particolare:
    • Se il file non è aperto per la lettura della sequenza di input non può essere letto.
    • Se il file non è aperto per la scrittura, la sequenza di output non può essere scritta.
    • Una posizione del file comune viene mantenuta sia per la sequenza di input che per la sequenza di output.

Ciò significa che quando si utilizza un std::basic_fstream, che di default utilizza un std::basic_filebuf, la posizione singolo file viene spostato da entrambi seekp() e seekg(); a meno che non si utilizzi una variabile separata per memorizzare una delle posizioni in modo da poterla quindi cercare, non è possibile tenere traccia delle posizioni put e get in modo indipendente.

Le implicazioni del punto 2 sono che tra le letture e le scritture su un fstream è necessario svuotare il buffer o cercare la posizione del file quando si passa dall'output all'input e si deve essere alla fine del file o cercare il posizione del file quando si cambia da input a output.

Per i dettagli su queste restrizioni, vedere la sezione 7.19.5.3/7 dello standard C99 ("La funzione fopen") o 7.21.5.3/7 di C11.

+0

Grazie! Quindi quando consiglieresti di lavare il buffer? Lo svuoterei dopo ogni lettura e scrittura, o sarebbe meglio lasciarlo così com'è se stai facendo una serie di letture o una serie di scritture? – raphnguyen

+1

@raphnguyen Flussare il buffer è un'operazione relativamente costosa, di solito non è necessario svuotare manualmente a meno che non si passi dalla scrittura alla lettura e non si cerchi, a meno che non si abbia una buona ragione per svuotare lasciare che l'implementazione gestisca altri svuotamenti. – user657267