Molti altri post, come "Read whole ASCII file into C++ std::string" spiegano quali sono alcune opzioni ma non descrivono pro e contro di vari metodi in nessuna profondità. Voglio sapere perché un metodo è preferibile rispetto a un altro?Modo ottimale di leggere un file completo in una stringa usando fstream?
Tutti questi utilizzano std::fstream
per leggere il file in un std::string
. Non sono sicuro di quali siano i costi e i benefici di ciascun metodo. Supponiamo che questo sia per il caso comune in cui i file letti sono noti per essere di dimensioni ridotte e che la memoria possa facilmente adattarsi, la lettura chiara di un file multi-terrabyte in una memoria è una cattiva idea, indipendentemente da come lo si fa.
Il modo più comune dopo un paio di googles ricerche per leggere un intero file in uno std :: string comporta l'uso di std::getline
e aggiungendo un carattere di nuova riga ad esso dopo ogni riga. Questo mi sembra inutile, ma c'è qualche motivo di prestazioni o compatibilità che questo sia l'ideale?
std::string Results;
std::ifstream ResultReader("file.txt");
while(ResultReader)
{
std::getline(ResultReader, Results);
Results.push_back('\n');
}
Un altro modo in cui ho messo insieme è quello di cambiare il delimitatore getline quindi non è qualcosa nel file. Il char EOF non sembra essere nel mezzo del file, quindi sembra un candidato probabile. Questo include un cast quindi c'è almeno un motivo per non farlo, ma questo legge un file in una volta senza concatenazione di stringhe. Presumibilmente vi è ancora un costo per i controlli delimitatori. Ci sono altri buoni motivi per non farlo?
std::string Results;
std::ifstream ResultReader("file.txt");
std::getline(ResultReader, Results, (char)std::char_traits<char>::eof());
Il cast significa che su sistemi che definiscono std :: :: char_traits eof() come qualcosa di diverso da -1 potrebbe avere problemi. È un motivo pratico per non scegliere questo rispetto ad altri metodi che utilizzano std::getline
e string::push_pack('\n')
.
Come fa queste confronta con gli altri modi di leggere il file in una sola volta come in questa domanda: Read whole ASCII file into C++ std::string
std::ifstream ResultReader("file.txt");
std::string Results((std::istreambuf_iterator<char>(ResultReader)),
std::istreambuf_iterator<char>());
Sembrerebbe questo sarebbe meglio. Trasferisce quasi tutto il lavoro sulla libreria standard che dovrebbe essere fortemente ottimizzato per la piattaforma indicata. Non vedo alcun motivo per i controlli oltre alla validità del flusso e alla fine del file. È questo ideale o ci sono problemi con ciò che non si vede.
Lo standard o i dettagli di alcune implementazioni forniscono motivi per preferire un metodo piuttosto che un altro? Ho perso qualche metodo che potrebbe rivelarsi ideale in un'ampia varietà di circostanze?
Qual è il modo più semplice, più idiomatico, più efficiente e conforme allo standard per leggere un intero file in un std::string
?
EDIT - 2 Questa domanda mi ha spinto a scrivere una piccola suite di benchmark. Sono licenza MIT ed è disponibile su GitHub a: https://github.com/Sqeaky/CppFileToStringExperiments
più veloce - TellSeekRead e CTellSeekRead- Questi hanno il sistema di fornire un facile per ottenere la dimensione e legge il file in una sola volta.
Più veloce - Getline Appending e Eof - Il controllo dei caratteri non sembra imporre alcun costo.
Fast - RdbufMove e Rdbuf - Lo std :: move sembra non fare alcuna differenza nel rilascio.
Lento - Iterator, BackInsertIterator e AssignIterator - Qualcosa non funziona con iteratori e flussi di input. Il lavoro è fantastico nella memoria, ma non qui. Detto questo, alcuni di questi sono più veloci di altri.
Ho aggiunto tutti i metodi suggeriti finora, compresi quelli nei collegamenti. Sarei grato se qualcuno potesse eseguirlo su Windows e con altri compilatori. Al momento non ho accesso a una macchina con NTFS e si è notato che questo e i dettagli del compilatore potrebbero essere importanti.
Per quanto riguarda la misurazione della semplicità e dell'idiomatica, come li misuriamo oggettivamente? La semplicità sembra fattibile, forse usare qualcosa di LOC e di complessità ciclomatica, ma come qualcosa di idiomatico sembra puramente soggettivo.
possibile duplicato del [Leggi l'intero file ASCII in C++ std :: string ] (http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring) –
La risposta collegata utilizza seek/tell per trovare la lunghezza del file. Se sai che è un file normale, è più semplice usare stat. – stark
'stat' è conforme allo standard, ma lo standard è POSIX. – user4581301