web-dev-qa-db-fra.com

Comment puis-je obtenir la taille d'un fichier en C?

Duplicate possible:
Comment déterminez-vous la taille d'un fichier en C?

Comment puis-je connaître la taille d'un fichier que j'ai ouvert avec une application écrite en C? Je voudrais connaître la taille, parce que je veux mettre le contenu du fichier chargé dans une chaîne que j'alloue avec malloc(). Juste écrire malloc(10000*sizeof(char)); est à mon humble avis une mauvaise idée.

359
Nino

Vous devez chercher à la fin du fichier puis demander le poste:

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

Vous pouvez alors chercher en arrière, par exemple:

fseek(fp, 0L, SEEK_SET);

ou (si vous voulez aller au début)

rewind(fp);
472
Rob Walker

Utilisation de la bibliothèque standard:

En supposant que votre implémentation prend en charge de manière significative SEEK_END:

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:

Vous pouvez utiliser stat (si vous connaissez le nom du fichier) ou fstat (si vous avez le descripteur de fichier).

Voici un exemple pour stat:

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

Win32:

Vous pouvez utiliser GetFileSize ou GetFileSizeEx .

355
Greg Hewgill

Si vous avez le descripteur de fichier, fstat() renvoie une structure de statistiques contenant la taille du fichier.

#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;
104
PiedPiper

J'ai fini par créer une fonction fsize courte et agréable (note, pas de vérification d'erreur)

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

C'est un peu ridicule que la bibliothèque standard C n'ait pas une telle fonction, mais je peux comprendre pourquoi ce serait difficile car tous les "fichiers" n'ont pas une taille (par exemple /dev/null)

17
Earlz

Avez-vous envisagé de ne pas calculer la taille du fichier et de simplement agrandir le tableau si nécessaire? Voici un exemple (avec vérification d'erreur ommitted):

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

Cela présente l’avantage de fonctionner même pour les flux dans lesquels il est impossible d’obtenir la taille du fichier (comme stdin).

10
Pat Morin

Comment utiliser lseek / fseek / stat / fstat pour obtenir la taille du fichier?

#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 == (long)-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 == (off_t)-1)
    {
        printf("failed to lseek %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] seek_filesize - file: %s, size: %lld\n", filename, 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;
}
10
lezard

Si vous êtes sur Linux, envisagez sérieusement d'utiliser simplement la fonction g_file_get_contents de glib. Il gère tout le code pour charger un fichier, allouer de la mémoire et gérer les erreurs.

9
Ben Combee