ifstream::open: Schneller mit ios::binary?
-
SeppJ schrieb:
So ist beispielsweise das Ergebnis der tell-Funktionen beispielsweise nur dafür gedacht, um damit die seek-Funktionen aufzurufen und nicht - wie es gerne oft vorgemacht wird - um damit beispielsweise die Größe einer Datei zu bestimmen. Das gilt übrigens ebenso im Binarymodus für bestimmte Fälle (zum Beispiel insbesondere bei der Positionierung am Dateiende, um die es hier anscheinend geht).
Oh, verdammt. Tja, wird halt überall so gemacht (und hier http://stackoverflow.com/a/22986486/1884226 steht, dass man sich unter Windows darauf verlassen kann..).
Aber dass man in Bytes springt (bin. mode) und ios::beg/cur/end korrekt sind, davon kann man schon ausgehen, oder?
Und könnte man die Dateigröße dann nicht mit end - beg bekommen?Warum ist das so kompliziert

-
Moly schrieb:
Warum ist das so kompliziert

Das ist gar nicht kompliziert.
Du hast Dich nur irgendwie verlaufen. Schau Dir die Funktion
statan. Der übergibst Du den Dateinamen und einen Zeiger auf eine stat-Struktur und sie liefert unter anderem die Dateigrösse. Und die Fehlerprüfung nicht vergessen!So einfach ist das.
Mit ifstream ist es ineffizient und komplizierter. Wobei es auch nicht wirklich kompliziert ist. Datei öffnen (std::ifstream::open), auf das Ende positionieren (std::istream::seekg) und die Position auslesen (std::istream::tellg).
-
SeppJ hat doch gerade 2x gesagt, dasss dies nicht korrekt ist

Ich finde es kompliziert, weil wozu hat man fstream, wenn man scheinbar nicht mal verlässlich die Dateigröße bestimmen kann...
-
Moly schrieb:
SeppJ hat doch gerade 2x gesagt, dasss dies nicht korrekt ist

Ich finde es kompliziert, weil wozu hat man fstream, wenn man scheinbar nicht mal verlässlich die Dateigröße bestimmen kann...
Wozu habe ich einen Hammer wenn ich noch nicht mal verlässlich eine Schraube damit eindrehen kann
.Man hat fstream um Dateien zu lesen und zu schreiben. Es ist eben nicht dafür gedacht, die Dateigröße zu bestimmen.
-
Okay, aber um vernünftig lesen/schreiben zu können, muss man doch vom Anfang bis zum Ende springen können.
Und die Differenz muss dann doch die Dateigröße sein (binary mode)?!
-
Moly schrieb:
Okay, aber um vernünftig lesen/schreiben zu können, muss man doch vom Anfang bis zum Ende springen können.
Naja.
Und die Differenz muss dann doch die Dateigröße sein (binary mode)?!
Naja. Manche System unterstützen "Löcher" in Dateien, wenn man an Stellen außerhalb des Endes seeked. Andere System nicht. Es kann sein, dass die "Löcher" mitgezählt werden bei tellg(), oder nicht.
Was spricht gegen?
long GetFileSize(std::string filename) { struct stat stat_buf; int rc = stat(filename.c_str(), &stat_buf); return rc == 0 ? stat_buf.st_size : -1; }(http://stackoverflow.com/a/6039648)
Ist vermutlich schneller und muss die Datei nicht öffnen.
-
SeppJ schrieb:
iospeed schrieb:
2. seekg und tellg müssen im Text-Modus nicht unbedingt unterstüzt werden. (Und im Binary-Modus ebenfalls nicht.)
Unterstützt werden müssen sie schon, es gibt bloß den ausdrücklichen Hinweis, dass das Ergebnis vielleicht nicht das ist, was man erwartet. So ist beispielsweise das Ergebnis der tell-Funktionen beispielsweise nur dafür gedacht, um damit die seek-Funktionen aufzurufen und nicht - wie es gerne oft vorgemacht wird - um damit beispielsweise die Größe einer Datei zu bestimmen.
Da muss ich doch nochmal nachfragen. Wo steht, dass das Ergebnis der tellg-Funktion nicht dafür geeignet ist? Ich bin der Meinung, dass man mit seekg und tellg durchaus die Grösse der Datei herausfinden kann.
Wobei man natürlich fragen kann, was man wissen will. Die Grösse einer Datei ist nicht zwangsweise die Anzahl der Bytes, die im Dateisystem belegt werden. Es gibt Sparse-Dateien, die Lücken aufweise. Aber eigentlich sind diese Lücken für eine Applikation transparent.
PS: Ich habe mal ein sparsefile angelegt mit:
dd if=/dev/zero of=sparsefile bs=1 count=0 seek=10MDiesem Programm:
#include <iostream> #include <fstream> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int main(int argc, char* argv[]) { struct stat st; stat("sparsefile", &st); std::cout << st.st_size << ' ' << st.st_blocks << std::endl; std::ifstream f("sparsefile"); f.seekg(0, std::ios_base::end); std::cout << f.tellg() << std::endl; }liefert dann:
10485760 0 10485760Also zumindest auf meinem System (Fedora mit ext4) liefert seekg/tellg die Dateigrösse. Wobei die Datei viel weniger Platz auf der Platte belegt (nämlich 0).
-
tntnet schrieb:
SeppJ schrieb:
iospeed schrieb:
2. seekg und tellg müssen im Text-Modus nicht unbedingt unterstüzt werden. (Und im Binary-Modus ebenfalls nicht.)
Unterstützt werden müssen sie schon, es gibt bloß den ausdrücklichen Hinweis, dass das Ergebnis vielleicht nicht das ist, was man erwartet. So ist beispielsweise das Ergebnis der tell-Funktionen beispielsweise nur dafür gedacht, um damit die seek-Funktionen aufzurufen und nicht - wie es gerne oft vorgemacht wird - um damit beispielsweise die Größe einer Datei zu bestimmen.
Da muss ich doch nochmal nachfragen. Wo steht, dass das Ergebnis der tellg-Funktion nicht dafür geeignet ist? Ich bin der Meinung, dass man mit seekg und tellg durchaus die Grösse der Datei herausfinden kann.
Im Standard natürlich. Dieser verweist über 5 Ecken auf den C-Standard und dieser wiederum gibt auf 5 verschiedene Stellen verteilt das wieder, was hier im Thread schon gesagt wurde.
Kurzwiedergabe:
fseek ans Ende muss nicht notwendigerweise genau ans Ende springen. Da kann beispielsweise Padding am Ende sein.
ftell am Ende gibt für Binärstreams zwar tatsächlich die Dateigröße an, aber wegen obigem Punkt ist man nicht garantiert am Ende, sondern vielleicht dahinter.
Und für Textstreams haben die Werte natürlich überhaupt nichts mit der Zahl der lesbaren Zeichen zu tun.Also zumindest auf meinem System (Fedora mit ext4) liefert seekg/tellg die Dateigrösse.
Den wichtigen Teil habe ich markiert. Unter POSIXen kannst du dich da drauf verlassen, dass das tatsächlich funktioniert, weil dies weitere Spezifikationen macht. Unter Windows wird's schon heikler. Und wer weiß, was andere exotische Systeme machen?
Und in jedem Fall ist das Öffnen der Datei überhaupt nötig oder gar eine gute Idee, um deren Größe heraus zu finden. Was ist, wenn die Datei gelockt ist oder du keine Leserechte hast? Gibt dein Programm dann auf?
-
Danke an alle.
stat (_wstat64) ist sogar am schnellsten, obwohl da ziemlich viele Informationen ausgelesen werden.
(GetFileSizeEx(OPEN_EXISTING) war etwa 50% langsamer, fstreams noch etwas langsamer)
-
Moly schrieb:
Danke an alle.
stat (_wstat64) ist sogar am schnellsten, obwohl da ziemlich viele Informationen ausgelesen werden.
(GetFileSizeEx(OPEN_EXISTING) war etwa 50% langsamer, fstreams noch etwas langsamer)Und nur zur Info: Wenns um Dateien geht, ist eh jede Geschwindigkeit verloren, ich würd mich nicht darum kümmern.
-
Nathan schrieb:
Und nur zur Info: Wenns um Dateien geht, ist eh jede Geschwindigkeit verloren, ich würd mich nicht darum kümmern.
Das klingt ja eher nach einem Programm, das Informationen über das Dateisystem ausgibt, anstatt tatsächlich Daten zu lesen. Da fände ich das schon ziemlich wichtig und man kann auch jede Menge Sachen richtig oder falsch machen.