Wie bestimmt man die Größe einer Datei in C?

Lesezeit: 9 Minuten

andrewrks Benutzeravatar
andrewrk

Wie kann ich die Größe einer Datei in Byte ermitteln?

#include <stdio.h>

unsigned int fsize(char* file){
  //what goes here?
}

  • 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* filewarum nicht FILE* 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 und read. Vorsichtig sein.

    – Benutzer26742873

    16. Februar 2021 um 2:54 Uhr

Benutzeravatar von T Percival
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:

  • Machte das Dateinamen-Argument a const char.
  • Korrigiert die struct stat Definition, der der Variablenname fehlte.
  • Kehrt zurück -1 auf Fehler statt 0was 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=64Andernfalls 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

Benutzeravatar von Orion Edwards
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

Benutzeravatar von Derek Park
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
}

Posix

Das Posix Standard hat seine eigene Methode, um die Dateigröße zu ermitteln.

Umfassen die sys/stat.h Kopfzeile, um die Funktion zu verwenden.

Zusammenfassung

  • Erhalten Sie Dateistatistiken mit stat(3).
  • Erhalten Sie die st_size Eigentum.

Beispiele

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);
}

ANSI-C (Standard)

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!

Zusammenfassung

  • Suchen Sie die Datei bis zum Ende mit fseek(3).
  • Holen Sie sich die aktuelle Position mit ftell(3).

Beispiel

#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ückkehren 0 wenn die Datei eine Pipe ist oder stdin.

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

Benutzeravatar von pmttavara
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

1424620cookie-checkWie bestimmt man die Größe einer Datei in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy