Wie kann ich die Größe einer Datei in C erhalten? [duplicate]

Lesezeit: 12 Minuten

[*]
Nino

Wie kann ich die Größe einer Datei ermitteln, die ich mit einer in C geschriebenen Anwendung geöffnet habe? Ich würde gerne die Größe wissen, weil ich den Inhalt der geladenen Datei in einen String stecken möchte, den ich mit alloziiere malloc(). Nur schreiben malloc(10000*sizeof(char)); ist IMHO eine schlechte Idee.

  • Beachten Sie, dass sizeof(char) per Definition 1 ist.

    – Randy Proctor

    29. Oktober 2009 um 13:44 Uhr

  • Ja, aber der Compiler einer esoterischen Plattform könnte char als 2 Bytes definieren – dann weist das Programm mehr als nötig zu. Man kann sich nie sicher sein.

    – Nathan Osmann

    5. Januar 2010 um 2:50 Uhr

  • @George ein “Compiler für esoterische Plattformen”, bei dem sizeof(char) != 1 kein echter C-Compiler ist. Selbst wenn ein Zeichen 32 Bit lang ist, wird es immer noch 1 zurückgeben.

    – Andrew Flanagan

    6. Dezember 2010 um 17:03 Uhr

  • @George: Der C- (und C++) Standard garantiert das sizeof(char)==1. Siehe zBparashift.com/c++-faq-lite/intrinsic-types.html#faq-26.1

    – schleske

    8. Februar 2011 um 13:40 Uhr


  • Ich bevorzuge eigentlich malloc(x*sizeof(char)); zu malloc(x); bei der Zuweisung von x Zeichen. Ja, sie kompilieren immer zum Gleichen, aber ich mag die Konsistenz mit anderen Speicherzuweisungen.

    – geschmolzen

    16. April 2011 um 1:16 Uhr

Benutzeravatar von Rob Walker
Rob Walker

Sie müssen bis zum Ende der Datei suchen und dann nach der Position fragen:

fseek(fp, 0L, SEEK_END);
sz = ftell(fp);

Sie können dann zurücksuchen, z.

fseek(fp, 0L, SEEK_SET);

oder (wenn Sie zum Anfang gehen möchten)

rewind(fp);

  • @camh – Danke Mann. Dieser Kommentar löste ein Problem, das ich mit einem Dateigrößenalgorithmus hatte. Für die Aufzeichnung öffnet man eine Datei im Binärmodus, indem man ein ‘b’ an das Ende der Moduszeichenfolge von fopen setzt.

    – TED

    18. Mai 2010 um 10:42 Uhr

  • Du, ähm, benutzen rewind bevor die Leute vergessen, was es bedeutet

    – bobobobo

    23. September 2011 um 16:55 Uhr

  • Gibt ein signiertes Int zurück, das auf 2 GB begrenzt ist. Aber auf der positiven Seite könnte Ihre Datei negative 2 Milliarden Bytes lang sein, und sie sind darauf vorbereitet.

    – Seth

    13. Februar 2012 um 21:07 Uhr

  • length = lseek(fd, 0, SEEK_END)+1;

    – Wolodymyr M. Lisivka

    16. November 2012 um 16:24 Uhr

  • Aus fseek-Dokumentation “Bibliotheksimplementierungen dürfen SEEK_END nicht sinnvoll unterstützen (daher hat Code, der es verwendet, keine echte Standardportabilität).”

    – Mika Haarahiltunen

    2. September 2013 um 10:43 Uhr

Benutzeravatar von Greg Hewgill
Greg Hewgill

Verwendung der Standardbibliothek:

Angenommen, Ihre Implementierung unterstützt SEEK_END sinnvoll:

fseek(f, 0, SEEK_END); // seek to end of file
size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
// proceed with allocating memory and reading the file

Linux/POSIX:

Sie können verwenden stat (wenn Sie den Dateinamen kennen), oder fstat (wenn Sie den Dateideskriptor haben).

Hier ist ein Beispiel für stat:

#include <sys/stat.h>
struct stat st;
stat(filename, &st);
size = st.st_size;

Win32:

Sie können verwenden GetFileSize oder GetFileSizeEx.

  • Bitte beachten Sie, dass ich der Übersichtlichkeit halber auf eine Fehlerprüfung verzichtet habe.

    – Greg Hewgill

    26. Oktober 2008 um 21:23 Uhr

  • Sie brauchen den Dateinamen nicht – Sie können dafür fstat verwenden.

    – Tanktalus

    26. Oktober 2008 um 21:24 Uhr

  • Sie müssen auf die Adresse der Struktur zeigen. Die zweite Zeile sollte lauten: stat(filename, &st);

    – Vlad der Impala

    3. November 2009 um 21:16 Uhr

  • Im Interesse von -FATAL ERROR, EXITING habe ich die Fehlerprüfung weggelassen.

    – Buttle Butkus

    3. Februar 2012 um 9:55 Uhr

  • Die zweite Option ist die einzige, die Dateien größer als 2 GB anzeigen kann

    – Seth

    13. Februar 2012 um 21:52 Uhr

Benutzeravatar von PiedPiper
Rattenfänger

Wenn Sie den Dateideskriptor haben fstat() gibt eine Statistikstruktur zurück, die die Dateigröße enthält.

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

// fd = fileno(f); //if you have a stream (e.g. from fopen), not a file descriptor.
struct stat buf;
fstat(fd, &buf);
off_t size = buf.st_size;

  • Fügen Sie “fd = fileno(f);” hinzu wenn Sie einen Stream haben (z. B. von fopen), keinen Dateideskriptor. Benötigt Fehlerprüfung.

    – ysth

    26. Oktober 2008 um 21:24 Uhr

  • Natürlich braucht es eine Fehlerprüfung – das würde das Beispiel nur verkomplizieren.

    – Rattenfänger

    26. Oktober 2008 um 21:28 Uhr

  • Dies ist meiner Meinung nach die beste wirkliche Antwort, und ich denke, wir alle haben unsere Stützräder zum größten Teil in C abgeschaltet. Brauchen wir in unseren Beispielen wirklich eine Fehlerprüfung und anderen unnötigen Code, es ist schlimm genug, dass M $ DN es tut ihre, lassen Sie uns nicht nachziehen, sondern sagen Sie am Ende einfach “Stellen Sie sicher, dass Sie eine Fehlerprüfung hinzufügen” und fertig.

    – Osirisgothra

    7. November 2013 um 16:45 Uhr


  • VIELE Benutzer von SO sind Studenten von C, keine Altmeister. Daher sollte der in den Antworten angegebene Code die Fehlerprüfung anzeigen, damit der Schüler den richtigen Weg zum Codieren lernt.

    – Benutzer3629249

    23. Februar 2015 um 18:30 Uhr

  • Es gibt das Detail, dass (f)stat() die Gesamtbytes der Blockzuordnung zurückgibt, während die Sequenz fseek() / ftell() die Anzahl der Bytes zurückgibt, bevor EOF angetroffen wird.

    – Benutzer3629249

    23. Februar 2015 um 18:32 Uhr

Am Ende habe ich es nur kurz und bündig gemacht fsize Funktion (Hinweis, keine Fehlerprüfung)

int fsize(FILE *fp){
    int prev=ftell(fp);
    fseek(fp, 0L, SEEK_END);
    int sz=ftell(fp);
    fseek(fp,prev,SEEK_SET); //go back to where we were
    return sz;
}

Es ist irgendwie albern, dass die Standard-C-Bibliothek keine solche Funktion hat, aber ich kann sehen, warum es schwierig wäre, da nicht jede “Datei” eine Größe hat (zum Beispiel /dev/null)

Wie benutzt man Ich suche/fseek/Stat/fstat Dateigröße bekommen?

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

void
fseek_filesize(const char *filename)
{
    FILE *fp = NULL;
    long off;

    fp = fopen(filename, "r");
    if (fp == NULL)
    {
        printf("failed to fopen %s\n", filename);
        exit(EXIT_FAILURE);
    }

    if (fseek(fp, 0, SEEK_END) == -1)
    {
        printf("failed to fseek %s\n", filename);
        exit(EXIT_FAILURE);
    }

    off = ftell(fp);
    if (off == -1)
    {
        printf("failed to ftell %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] fseek_filesize - file: %s, size: %ld\n", filename, off);

    if (fclose(fp) != 0)
    {
        printf("failed to fclose %s\n", filename);
        exit(EXIT_FAILURE);
    }
}

void
fstat_filesize(const char *filename)
{
    int fd;
    struct stat statbuf;

    fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
    if (fd == -1)
    {
        printf("failed to open %s\n", filename);
        exit(EXIT_FAILURE);
    }

    if (fstat(fd, &statbuf) == -1)
    {
        printf("failed to fstat %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] fstat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);

    if (close(fd) == -1)
    {
        printf("failed to fclose %s\n", filename);
        exit(EXIT_FAILURE);
    }
}

void
stat_filesize(const char *filename)
{
    struct stat statbuf;

    if (stat(filename, &statbuf) == -1)
    {
        printf("failed to stat %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] stat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);

}

void
seek_filesize(const char *filename)
{
    int fd;
    off_t off;

    if (filename == NULL)
    {
        printf("invalid filename\n");
        exit(EXIT_FAILURE);
    }

    fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
    if (fd == -1)
    {
        printf("failed to open %s\n", filename);
        exit(EXIT_FAILURE);
    }

    off = lseek(fd, 0, SEEK_END);
    if (off == -1)
    {
        printf("failed to lseek %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] seek_filesize - file: %s, size: %lld\n", filename, (long long) off);

    if (close(fd) == -1)
    {
        printf("failed to close %s\n", filename);
        exit(EXIT_FAILURE);
    }
}

int
main(int argc, const char *argv[])
{
    int i;

    if (argc < 2)
    {
        printf("%s <file1> <file2>...\n", argv[0]);
        exit(0);
    }

    for(i = 1; i < argc; i++)
    {
        seek_filesize(argv[i]);
        stat_filesize(argv[i]);
        fstat_filesize(argv[i]);
        fseek_filesize(argv[i]);
    }

    return 0;
}

  • oder if(off == (-1L)) kein Bedarf für (long)

    – Immobilis

    1. Juni 2018 um 0:45 Uhr

  • ftell gibt a zurück long, Unglücklicherweise. Du brauchst ftello zurückgeben ein off_t. (Oder anscheinend unter Windows, _ftelli64()weil sie es anscheinend lieben, das Schreiben von portablem Code zu erschweren.) Siehe Diskussion zu einer anderen Antwort

    – Peter Cordes

    25. November 2021 um 11:33 Uhr


  • fstat ist nur sinnvoll, wenn Sie bereits eine geöffnete Datei haben, oder als Teil des Prozesses, sie zu öffnen. Dein fstat_filesize ist nichts, was Sie jemals in dieser Form verwenden möchten, nur wenn Sie das tatsächlich behalten würden fd herum und lese daraus oder so etwas. offen/fstat/close hat keinen Vorteil gegenüber stat; Ich hätte diese Funktion geschrieben, um a zu nehmen FILE *fp (verwenden fileno()) oder int fd. Ich denke, Ihre Funktionen sind nicht dazu gedacht, wie sie sind, verwendet zu werden, da sie die Ergebnisse nur drucken, anstatt sie zurückzugeben.

    – Peter Cordes

    25. November 2021 um 11:38 Uhr


  • Auch da kommst du nicht vorbei O_CREAT zu opendas 3. Argument wird nicht verwendet. S_IRUSR | S_IRGRP ist dort nicht aussagekräftig. Wenn open war werde die Datei erstellen, die es geben würde 0440 auch bekannt r--r----- Berechtigungen (die alles andere daran hindern würden, sie zu öffnen und darauf zu schreiben), aber es geht nicht ohne O_CREAT also die int open(const char *pathname, int flags); Form des Prototyps gilt. man7.org/linux/man-pages/man2/open.2.html

    – Peter Cordes

    25. November 2021 um 11:42 Uhr


  • Abgesehen von der Gestaltung von fstat_filesize, ja, dies ist ein nützliches Beispiel für die Fehlerprüfung. Außer du solltest fprintf(stderr, ... mit deinen Fehlermeldungen. Und in den Funktionen, die POSIX verwenden stat und Freunde, sollten Sie verwenden strerror als Teil davon, um einen tatsächlichen Grund für den Fehler zu erhalten, wie z. B. “keine solche Datei oder kein solches Verzeichnis”. ENOENT oder “Erlaubnis verweigert” für EPERM. Das ist viel nützlicher und der Standardweg, um Fehler in Unix-Programmen zu melden. (Systemaufruf und Dateiname sind besser als nichts, der Benutzer denkt möglicherweise nicht an Berechtigungen, wenn Sie es ihnen nicht sagen.)

    – Peter Cordes

    25. November 2021 um 12:02 Uhr

Benutzeravatar von Pat Morin
Pat Morin

Haben Sie darüber nachgedacht, die Dateigröße nicht zu berechnen und das Array bei Bedarf einfach zu vergrößern? Hier ist ein Beispiel (ohne Fehlerprüfung):

#define CHUNK 1024

/* Read the contents of a file into a buffer.  Return the size of the file 
 * and set buf to point to a buffer allocated with malloc that contains  
 * the file contents.
 */
int read_file(FILE *fp, char **buf) 
{
  int n, np;
  char *b, *b2;

  n = CHUNK;
  np = n;
  b = malloc(sizeof(char)*n);
  while ((r = fread(b, sizeof(char), CHUNK, fp)) > 0) {
    n += r;
    if (np - n < CHUNK) { 
      np *= 2;                      // buffer is too small, the next read could overflow!
      b2 = malloc(np*sizeof(char));
      memcpy(b2, b, n * sizeof(char));
      free(b);
      b = b2;
    }
  }
  *buf = b;
  return n;
}

Dies hat den Vorteil, dass es auch für Streams funktioniert, in denen es unmöglich ist, die Dateigröße zu erhalten (wie stdin).

  • oder if(off == (-1L)) kein Bedarf für (long)

    – Immobilis

    1. Juni 2018 um 0:45 Uhr

  • ftell gibt a zurück long, Unglücklicherweise. Du brauchst ftello zurückgeben ein off_t. (Oder anscheinend unter Windows, _ftelli64()weil sie es anscheinend lieben, das Schreiben von portablem Code zu erschweren.) Siehe Diskussion zu einer anderen Antwort

    – Peter Cordes

    25. November 2021 um 11:33 Uhr


  • fstat ist nur sinnvoll, wenn Sie bereits eine geöffnete Datei haben, oder als Teil des Prozesses, sie zu öffnen. Dein fstat_filesize ist nichts, was Sie jemals in dieser Form verwenden möchten, nur wenn Sie das tatsächlich behalten würden fd herum und lese daraus oder so etwas. offen/fstat/close hat keinen Vorteil gegenüber stat; Ich hätte diese Funktion geschrieben, um a zu nehmen FILE *fp (verwenden fileno()) oder int fd. Ich denke, Ihre Funktionen sind nicht dazu gedacht, wie sie sind, verwendet zu werden, da sie die Ergebnisse nur drucken, anstatt sie zurückzugeben.

    – Peter Cordes

    25. November 2021 um 11:38 Uhr


  • Auch da kommst du nicht vorbei O_CREAT zu opendas 3. Argument wird nicht verwendet. S_IRUSR | S_IRGRP ist dort nicht aussagekräftig. Wenn open war werde die Datei erstellen, die es geben würde 0440 auch bekannt r--r----- Berechtigungen (die alles andere daran hindern würden, sie zu öffnen und darauf zu schreiben), aber es geht nicht ohne O_CREAT also die int open(const char *pathname, int flags); Form des Prototyps gilt. man7.org/linux/man-pages/man2/open.2.html

    – Peter Cordes

    25. November 2021 um 11:42 Uhr


  • Abgesehen von der Gestaltung von fstat_filesize, ja, dies ist ein nützliches Beispiel für die Fehlerprüfung. Außer du solltest fprintf(stderr, ... mit deinen Fehlermeldungen. Und in den Funktionen, die POSIX verwenden stat und Freunde, sollten Sie verwenden strerror als Teil davon, um einen tatsächlichen Grund für den Fehler zu erhalten, wie z. B. “keine solche Datei oder kein solches Verzeichnis”. ENOENT oder “Erlaubnis verweigert” für EPERM. Das ist viel nützlicher und der Standardweg, um Fehler in Unix-Programmen zu melden. (Systemaufruf und Dateiname sind besser als nichts, der Benutzer denkt möglicherweise nicht an Berechtigungen, wenn Sie es ihnen nicht sagen.)

    – Peter Cordes

    25. November 2021 um 12:02 Uhr

Benutzeravatar von GabrielF
GabrielF

Wenn Sie Linux verwenden, sollten Sie ernsthaft erwägen, nur die zu verwenden g_file_get_contents Funktion von glib. Es verarbeitet den gesamten Code zum Laden einer Datei, zum Zuweisen von Speicher und zum Behandeln von Fehlern.

  • Wenn Sie Linux verwenden und wollen eine Abhängigkeit von glib haben, das heißt.

    – JesperE

    26. Oktober 2008 um 22:25 Uhr

  • Kein so schlimmes Problem, da glib jetzt sowohl von GTK- als auch von KDE-Anwendungen verwendet wird. Es ist auch unter Mac OS X und Windows verfügbar, aber dort nicht annähernd so Standard.

    – Ben Combee

    29. Oktober 2008 um 19:23 Uhr

  • Aber ist Glib nicht eine C++-Bibliothek? Die Frage forderte C

    – David Appleton

    21. Juni 2013 um 9:54 Uhr

  • @DaveAppleton: Nein, Glib ist eher eine einfache C-Bibliothek, nicht C++.

    – Nate CK

    20. Februar 2014 um 4:13 Uhr

  • @BenCombee glib ist nicht auf Android, habe ich zuletzt überprüft.

    – Wyatt Ward

    1. Mai 2017 um 4:40 Uhr

1427810cookie-checkWie kann ich die Größe einer Datei in C erhalten? [duplicate]

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

Privacy policy