Dateigröße ermitteln
-
Auch nicht akzeptabel. Stell dir vor, der Dateizeiger steht auf Position x, und der Client sagt get_size(file). Wenn ich Client wäre, dann würde ich erwarten, dass der Dateizeiger danach immer noch auf Position x steht.
-
geht ja auch, man speichert dann die aktuelle file position einfach in einer variablen und setzt per fseek dann wieder auf die position:
long get_size (FILE *file) { long pos=0; long size=0; pos=ftell(file); rewind(file); while (fgetc(file)!=EOF) size++; fseek (file,pos,SEEK_SET); return size; }
-
Und wieso benutzt du dann nicht gleich fseek mit SEEK_END (oder wie das heisst)?
-
fseek (file,bytes_from_position,position); SEEK_END Dateiende \\bringt ja nix SEEK_SET Dateianfang SEEK_CUR Jetzige position
-
MasterCounter schrieb:
SEEK_END Dateiende \\bringt ja nix
Wieso das?
-
Das ist doch wirklich einfach:
FILE* file = fopen("blah.txt", "rb"); fseek(file, 0L, SEEK_END); printf("Dateigröße: %d Bytes\n", ftell(file)); fclose(file);
~cp
-
Mann, mann, mann. Hatte eigentlich gehofft, dass MasterCounter selbst drauf kommt, aber...naja, egal.
-
groovemaster schrieb:
Mann, mann, mann. Hatte eigentlich gehofft, dass MasterCounter selbst drauf kommt, aber...naja, egal.
LOL
-
Diese Lösung ist mir ja bekannt, aber das verhaklten von fseek mit SEEK_END ist laut Standard undefiniert, darum wäre meine Lösung doch eigentlich sicherer oder?
In N869 ist es Fussnote 211:
Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state.
Oder vertue ich mich da jetzt grad völlig (<-was ich ja nicht glaube
)
-
code_pilot schrieb:
Das ist doch wirklich einfach:
FILE* file = fopen("blah.txt", "rb"); fseek(file, 0L, SEEK_END); printf("Dateigröße: %d Bytes\n", ftell(file)); fclose(file);
Einfach vielleicht, aber hickehackefalsch. fseek(f,0,SEEK_END) muß nicht funktionieren. Bei Binärdateien ist das Verhalten sogar undefiniert.
-
MasterCounter schrieb:
Diese Lösung ist mir ja bekannt, aber das verhaklten von fseek mit SEEK_END ist laut Standard undefiniert, darum wäre meine Lösung doch eigentlich sicherer oder?
Was willst Du eigentlich machen? Die Datei in den Speicher übertragen?
-
Ich wollte einfach nur eine sichere Lösung finden, um die Dateigröße zu ermitteln, denn diese braucht man ja um die Datei in ein char* oder ähnliches zu lesen. Was hältst du also von meiner Lösung? Müsste doch eigentlich sicher sein oder?
-
int Size; fseek( <DATEI>, 0, SEEK_END ); //Springt ans Ende Der Datei Size = ftell( <DATEI> ); //Ermittelt Größe in Bytes fseek( <DATEI> , 0, SEEK_SET ); //Springt wieder an Anfang (Wichtig!)
-
MasterCounter schrieb:
Ich wollte einfach nur eine sichere Lösung finden, um die Dateigröße zu ermitteln, denn diese braucht man ja um die Datei in ein char* oder ähnliches zu lesen. Was hältst du also von meiner Lösung? Müsste doch eigentlich sicher sein oder?
Ist nicht besonders schön, weil man die Datei eben zweimal abklappert, und außerdem kann man theoretisch Fälle konstruieren, wo while(fgetc(f)!=EOF) nicht erwartungsgemäß funktioniert (weil int und char gleich breit sind und man EOF nicht von einem gültigen char gleichen Zahlenwertes unterscheiden kann). Das ist allerdings ziemlich paranoid und somit nur zu berücksichtigen, wenn man maximal portabel bleiben will (sonst macht man die ganze Zeit Klimmzüge um ISO-konform zu bleiben). Also kann man das schon prinzipiell so machen, wie Du dir das vorstellst, aber man kann auch einfach mit realloc immer ausreichend Speicher bereitstellen, wenn's dir nur darum geht, die Datei in einen 'char*' zu bekommen.
-
wie sähe das dann mit realloc aus?
-
void* xrealloc(void *mem, size_t sz) { void *p = realloc(mem, sz); if (!p) { free(mem); ... exit(EXIT_FAILURE); } return p; } char *fgetfile(FILE *f) { char *p, *q; size_t mem_sz = INIT_MEM; /* beliebige Konstante */ size_t pos = 0; p = 0; while (1) { p = xrealloc(p, mem_sz); q = p + pos; while (q != p + mem_sz) { int c = fgetc(f); ++pos; if (c == EOF) { *q = '\0'; return p; } else *q++ = c; } mem_sz *= 2; /* Speicherbereich verdoppeln */ } return 0; /* nie erreicht, wenn der Quelltext so tut, wie ich mir das vorstelle */ }
Das ist jetzt einfach so runtergehackt, also vermutlich ist irgendwo noch ein Fehler drin. Außerdem kann man die Sache etwas beschleunigen, indem man andere Leseroutinen statt fgetc verwendet ...
Hast Du wirklich noch nie einen Anwednungsfall für realloc gesehen?
-
doch schon, aber in dynamischer speicherplatzverwaltung bin ich noch nicht so fit... hab vorher alles über malloc gemacht, darum hab ich nach einer sicheren möglichkeit gesucht die dateigröße zu ermitteln, vielen dank erstmal an dich!
-
MasterCounter schrieb:
Diese Lösung ist mir ja bekannt, aber das verhaklten von fseek mit SEEK_END ist laut Standard undefiniert, darum wäre meine Lösung doch eigentlich sicherer oder?
Das ist aber imo ziemlich paranoid. Der Standard sagt ja nur soviel, dass eine Implementation von SEEK_END für binäre Streams nicht unterstützt werden muss, bzw in erwarteter Weise funktionieren wird. Mit Unix oder Windows wird man da aber kaum Probleme haben.
Ansonsten hilf dir vielleicht das weiterSo, to go back to the original question, the best chance of "portably"
obtaining the (physical) size of a file (in bytes) is:long filesize(char *filename) { long size; FILE *fp; if ((fp = fopen(file, "r")) == NULL) return -2; fclose(fp); if ((fp = fopen(file, "ab")) == NULL) return -3; size = ftell(fp); fclose(fp) return size; }
Note that there are three error codes:
-1: ftell() has failed, check errno for further details
-2: the file doesn't exist or is read protected
-3: the file exists, but is write protectedDie Vorgehensweise hat aber einen nicht unerheblichen Nachteil, du brauchst Schreibzugriff.
-
Dieser Beitrag wurde gelöscht!
-
Dieser Beitrag wurde gelöscht!