Perché non riesco a leggere e aggiungere con std :: fstream su Mac OS X?
-
21-09-2019 - |
Domanda
Si consideri il seguente programma C ++, che prende un file e stampa ogni riga. Si tratta di una fetta di un programma più ampio in cui ho poi aggiungere al file, in base a quello che vedo.
#include <fstream>
using std::fstream;
#include <iostream>
#include <string>
using std::string;
int main()
{
fstream file("file.txt", fstream::in | fstream::out | fstream::app);
string line;
while (std::getline(file, line))
std::cerr << line << std::endl;
return 0;
}
Ora applicare questa versione di file.txt
(Una parola sulla prima riga, seguito da un ritorno a capo):
Rain
Sulla mia macchina (Snow Leopard), Questo stampa nulla. A ben vedere, la prima chiamata a getline non riesce. Stranamente, non riesce anche se posso aggiungere una seconda linea: ancora nulla viene stampato
Qualcuno può risolvere questo mistero?
Soluzione
Quando si dice:
fstream file("file.txt", fstream::in | fstream::out | fstream::app);
si apre il file in modalità append - vale a dire alla fine. Basta aprirlo in modalità di lettura:
fstream file("file.txt", fstream::in );
o utilizzare un ifstream:
ifstream file("file.txt" );
E naturalmente come suggerisce Earwicker, si dovrebbe sempre verificare che l'apertura è riuscita.
Se siete determinati ad aprire in modalità di aggiunta, è possibile spostare il puntatore di lettura esplicitamente:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main() {
fstream file( "afile.txt", ios::in | ios::out | ios::app );
if ( ! file.is_open() ) {
cerr << "open failed" << endl;
return 1;
}
else {
file.seekg( 0, ios::beg ); // move read pointer
string line;
while( getline( file, line ) ) {
cout << line << endl;
}
}
}
Modifica Sembra che la combinazione di flag utilizzati in apertura del file porta ad un comportamento specifica implementazione. Il codice precedente funziona con g ++ su Windows, ma non con g ++ su Linux.
Altri suggerimenti
Si dovrebbe verificare se il file è in realtà stato aperto:
if (!file)
std::cerr << "Oh dear" << std::endl;
Aggiornamento: , infatti, il file probabilmente è stato aperto, ma è in modalità di accodamento - vedere la risposta di NEII
. Aggiornamento 2: va bene, sbagliato di nuovo. In g di Leopard ++, almeno, il file non verrà aperto perché la bandiera app
è incompatibile con la bandiera in
. Quindi il controllo sopra stamperà Oh dear
.
In MSVC ++, si va avanti e si apre il file, a quanto pare con la posizione di lettura alla partenza, il che spiega il motivo per cui altre persone hanno visto il lavoro e mi scuso per aver dubitato loro veridicità!