Wie kann ich die Größe einer Datei in Byte ermitteln?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
andrewrk
Wie kann ich die Größe einer Datei in Byte ermitteln?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
T Perzival
Auf Unix-ähnlichen Systemen können Sie POSIX-Systemaufrufe verwenden: stat
auf einem Wegoder fstat
auf einem bereits geöffneten Dateideskriptor (POSIX ManpageLinux Manpage).
(Holen Sie sich einen Dateideskriptor von open(2)
oder fileno(FILE*)
in einem Stdio-Stream).
Basierend auf dem Code von NilObject:
#include <sys/stat.h>
#include <sys/types.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
return -1;
}
Änderungen:
const char
.struct stat
Definition, der der Variablenname fehlte.-1
auf Fehler statt 0
was für eine leere Datei mehrdeutig wäre. off_t
ist ein signierter Typ, daher ist dies möglich.Falls Sie es wollen fsize()
Um eine Fehlermeldung zu drucken, können Sie Folgendes verwenden:
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
fprintf(stderr, "Cannot determine size of %s: %s\n",
filename, strerror(errno));
return -1;
}
Auf 32-Bit-Systemen sollten Sie dies mit der Option kompilieren -D_FILE_OFFSET_BITS=64
Andernfalls off_t
hält nur Werte bis zu 2 GB. Siehe den Abschnitt „Verwendung von LFS“ in Unterstützung großer Dateien unter Linux für Details.
Dies ist Linux / Unix-spezifisch – wahrscheinlich lohnt es sich, darauf hinzuweisen, da in der Frage kein Betriebssystem angegeben wurde.
– Zeichnete Hall
2. August 2010 um 21:54 Uhr
Sie könnten wahrscheinlich den Rückgabetyp in ssize_t ändern und die Größe ohne Probleme aus einem off_t umwandeln. Es scheint sinnvoller zu sein, ein ssize_t zu verwenden 🙂 (Nicht zu verwechseln mit size_t, das unsigniert ist und nicht verwendet werden kann, um Fehler anzuzeigen.)
– T Perzival
6. August 2010 um 17:03 Uhr
Verwenden Sie für mehr portablen Code fseek
+ ftell
wie von Derek vorgeschlagen.
– Ciro Santilli OurBigBook.com
2. März 2015 um 7:57 Uhr
Verwenden Sie für mehr portablen Code fseek
+ ftell
wie von Derek vorgeschlagen. Nein. Die C-Standard stellt das ausdrücklich fest fseek()
zu SEEK_END
bei einer Binärdatei ist undefiniertes Verhalten. 7.19.9.2 Die fseek
Funktion … Ein Binärstrom muss nicht sinnvoll unterstützt werden fseek
Aufrufe mit einem where-Wert von SEEK_END
, und wie unten angemerkt, die aus Fußnote 234 auf p. 267 des verknüpften C-Standards, und die speziell gekennzeichnet sind fseek
zu SEEK_END
in einem binären Stream als undefiniertes Verhalten. .
– Andreas Henle
6. April 2016 um 10:54 Uhr
Aus Gnu-Libc-Handbuch: … [non-POSIX] Systeme unterscheiden zwischen Dateien, die Text enthalten, und Dateien, die Binärdaten enthalten, und die Eingabe- und Ausgabeeinrichtungen von ISO C sorgen für diese Unterscheidung. … In der GNU-C-Bibliothek und auf allen POSIX-Systemen gibt es keinen Unterschied zwischen Text-Streams und Binär-Streams. Wenn Sie einen Stream öffnen, erhalten Sie die gleiche Art von Stream, unabhängig davon, ob Sie nach einer Binärdatei fragen. Dieser Stream kann jeden Dateiinhalt verarbeiten und hat keine der Einschränkungen, die Textstreams manchmal haben.
– Kleiner Junge
14. August 2020 um 8:02 Uhr
Orion Edwards
Nicht verwenden int
. Dateien mit einer Größe von über 2 Gigabyte sind heutzutage gang und gäbe
Nicht verwenden unsigned int
. Dateien mit einer Größe von über 4 Gigabyte sind üblich, da etwas weniger üblicher Schmutz vorhanden ist
IIRC definiert die Standardbibliothek off_t
als vorzeichenlose 64-Bit-Ganzzahl, die jeder verwenden sollte. Wir können das in ein paar Jahren auf 128 Bit umdefinieren, wenn wir anfangen, 16 Exabyte-Dateien herumzuhängen.
Wenn Sie Windows verwenden, sollten Sie verwenden GetFileSizeEx – Es verwendet tatsächlich eine vorzeichenbehaftete 64-Bit-Ganzzahl, sodass Probleme mit 8-Exabyte-Dateien auftreten. Dummes Microsoft! 🙂
Ich habe Compiler verwendet, bei denen off_t 32 Bit ist. Zugegeben, dies gilt für eingebettete Systeme, auf denen 4-GB-Dateien weniger verbreitet sind. Wie auch immer, POSIX definiert auch off64_t und entsprechende Methoden, um zur Verwirrung beizutragen.
– Aaron Campbell
7. Juli 2016 um 20:12 Uhr
Ich liebe immer Antworten, die Windows annehmen und nichts anderes tun, als die Frage zu kritisieren. Könnten Sie bitte etwas hinzufügen, das POSIX-konform ist?
– SS Anne
27. April 2019 um 18:52 Uhr
@ JL2210 Die akzeptierte Antwort von Ted Percival zeigt eine Posix-konforme Lösung, daher sehe ich keinen Sinn darin, das Offensichtliche zu wiederholen. Ich (und 70 andere) dachten, dass das Hinzufügen des Hinweises über Windows und die Verwendung von vorzeichenbehafteten 32-Bit-Ganzzahlen zur Darstellung von Dateigrößen ein zusätzlicher Mehrwert war. Prost
– Orion Edwards
28. April 2019 um 4:32 Uhr
Derek Park
Matts Lösung sollte funktionieren, außer dass es C++ statt C ist und der anfängliche Tell nicht notwendig sein sollte.
unsigned long fsize(char* file)
{
FILE * f = fopen(file, "r");
fseek(f, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(f);
fclose(f);
return len;
}
Reparierte auch Ihre Zahnspange für Sie. 😉
Update: Das ist nicht wirklich die beste Lösung. Es ist unter Windows auf 4 GB Dateien beschränkt und wahrscheinlich langsamer als nur die Verwendung eines plattformspezifischen Aufrufs wie GetFileSizeEx
oder stat64
.
Ja du solltest. Wenn es jedoch keinen wirklich zwingenden Grund gibt, nicht plattformspezifisch zu schreiben, sollten Sie wahrscheinlich nur einen plattformspezifischen Aufruf anstelle des Open/Seek-End/Tell/Close-Musters verwenden.
– Derek Park
18. April 2012 um 4:10 Uhr
Sorry für die späte Antwort, aber ich habe hier ein großes Problem. Es führt dazu, dass die App beim Zugriff auf eingeschränkte Dateien (wie passwortgeschützte oder Systemdateien) hängen bleibt. Gibt es eine Möglichkeit, den Benutzer bei Bedarf nach einem Passwort zu fragen?
– Justin
29. März 2013 um 3:34 Uhr
@Justin, Sie sollten wahrscheinlich eine neue Frage speziell zu dem Problem öffnen, auf das Sie stoßen, und Details zu der Plattform angeben, auf der Sie sich befinden, wie Sie auf die Dateien zugreifen und wie das Verhalten ist.
– Derek Park
2. April 2013 um 15:04 Uhr
Sowohl C99 als auch C11 kehren zurück long int
aus ftell()
. (unsigned long)
Gießen verbessert die Reichweite nicht, da sie bereits durch die Funktion begrenzt ist. ftell()
geben Sie -1 im Fehlerfall zurück und werden mit der Besetzung verschleiert. Empfehlen fsize()
denselben Typ zurückgeben wie ftell()
.
– chux – Wiedereinsetzung von Monica
12. Januar 2014 um 22:03 Uhr
Ich stimme zu. Die Besetzung sollte dem ursprünglichen Prototyp in der Frage entsprechen. Ich kann mich jedoch nicht erinnern, warum ich es in unsigned long anstatt in unsigned int umgewandelt habe.
– Derek Park
27. Januar 2014 um 22:09 Uhr
** Tu das nicht (warum?):
Zitieren des C99-Standarddokuments, das ich online gefunden habe: “Setting the file position Indicator to end-of-file, as with
fseek(file, 0, SEEK_END)
hat ein undefiniertes Verhalten für einen binären Stream (wegen möglicher nachgestellter Nullzeichen) oder für jeden Stream mit zustandsabhängiger Codierung, der nicht sicher im anfänglichen Shift-Zustand endet.**
Ändern Sie die Definition in int, damit Fehlermeldungen übertragen werden können, und verwenden Sie dann fseek()
und ftell()
um die Dateigröße zu bestimmen.
int fsize(char* file) {
int size;
FILE* fh;
fh = fopen(file, "rb"); //binary mode
if(fh != NULL){
if( fseek(fh, 0, SEEK_END) ){
fclose(fh);
return -1;
}
size = ftell(fh);
fclose(fh);
return size;
}
return -1; //error
}
Das Posix Standard hat seine eigene Methode, um die Dateigröße zu ermitteln.
Umfassen die sys/stat.h
Kopfzeile, um die Funktion zu verwenden.
stat(3)
.st_size
Eigentum.Notiz: Es begrenzt die Größe auf 4GB
. Wenn nicht Fat32
Dateisystem verwenden Sie dann die 64bit-Version!
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat info;
stat(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat64 info;
stat64(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
Das ANSI-C bietet nicht direkt die Möglichkeit, die Länge der Datei zu bestimmen.
Wir müssen unseren Verstand benutzen. Im Moment verwenden wir den Seek-Ansatz!
#include <stdio.h>
int main(int argc, char** argv)
{
FILE* fp = fopen(argv[1]);
int f_size;
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
rewind(fp); // to back to start again
printf("%s: size=%ld", (unsigned long)f_size);
}
Wenn die Datei ist
stdin
oder ein Rohr. POSIX, ANSI-C wird nicht funktionieren.
Es wird zurückkehren0
wenn die Datei eine Pipe ist oderstdin
.Meinung: Du solltest benutzen Posix Standard statt. Weil es 64-Bit-Unterstützung hat.
struct _stat64
und __stat64()
für Windows.
– Bob Stein
17. April 2019 um 13:23 Uhr
Das letzte Beispiel ist falsch, fopen
nimmt zwei Argumente
– MM
17. Februar 2021 um 3:58 Uhr
In ISO C ist die Funktion ftell
garantiert nur dann die Anzahl der Bytes vom Anfang der Datei, wenn die Datei im Binärmodus geöffnet ist. Im Textmodus wird jedoch der Wert zurückgegeben von ftell
ist nicht spezifiziert und hat nur Bedeutung für fseek
.
– Andreas Wenzel
23. April um 3:41 Uhr
Und wenn Sie eine Windows-App erstellen, verwenden Sie die GetFileSizeEx API als CRT-Datei-I/O ist chaotisch, insbesondere zur Bestimmung der Dateilänge, aufgrund von Besonderheiten bei der Dateidarstellung auf verschiedenen Systemen;)
struct _stat64
und __stat64()
für Windows.
– Bob Stein
17. April 2019 um 13:23 Uhr
Das letzte Beispiel ist falsch, fopen
nimmt zwei Argumente
– MM
17. Februar 2021 um 3:58 Uhr
In ISO C ist die Funktion ftell
garantiert nur dann die Anzahl der Bytes vom Anfang der Datei, wenn die Datei im Binärmodus geöffnet ist. Im Textmodus wird jedoch der Wert zurückgegeben von ftell
ist nicht spezifiziert und hat nur Bedeutung für fseek
.
– Andreas Wenzel
23. April um 3:41 Uhr
pmttavara
Wenn Sie mit der Verwendung der std c-Bibliothek einverstanden sind:
#include <sys/stat.h>
off_t fsize(char *file) {
struct stat filestat;
if (stat(file, &filestat) == 0) {
return filestat.st_size;
}
return 0;
}
Das ist kein Standard-C. Es ist Teil des POSIX-Standards, aber nicht des C-Standards.
– Derek Park
11. August 2008 um 21:32 Uhr
Sie müssen eine Bibliotheksfunktion verwenden, um die Details einer Datei abzurufen. Da C völlig plattformunabhängig ist, müssen Sie uns mitteilen, für welche Plattform / welches Betriebssystem Sie entwickeln!
– Chris Roberts
11. August 2008 um 21:18 Uhr
Warum
char* file
warum nichtFILE* file
? -1– Benutzer12211554
12. September 2019 um 19:16 Uhr
@ user12211554 damit … nur
strlen
!– Benutzer26742873
16. Februar 2021 um 2:50 Uhr
Beachten Sie Folgendes: Die Datei kann zwischen wachsen
fsize
undread
. Vorsichtig sein.– Benutzer26742873
16. Februar 2021 um 2:54 Uhr