Est-ce une méthode recommandée pour calculer la taille d’un fichier en utilisant fseek ()?

En C, nous pouvons trouver la taille du fichier en utilisant la fonction fseek() . Comme,

 if (fseek(fp, 0L, SEEK_END) != 0) { // Handle repositioning error } 

Donc, j’ai une question, est-ce la méthode recommandée pour calculer la taille d’un fichier en utilisant fseek() et ftell() ?

Si vous êtes sous Linux ou un autre système comme UNIX, ce que vous voulez, c’est la fonction stat :

 struct stat statbuf; int rval; rval = stat(path_to_file, &statbuf); if (rval == -1) { perror("stat failed"); } else { printf("file size = %lld\n", (long long)statbuf.st_size; } 

Sous Windows sous MSVC, vous pouvez utiliser _stati64 :

 struct _stati64 statbuf; int rval; rval = _stati64(path_to_file, &statbuf); if (rval == -1) { perror("_stati64 failed"); } else { printf("file size = %lld\n", (long long)statbuf.st_size; } 

Contrairement à l’utilisation de fseek , cette méthode n’implique pas l’ouverture du fichier ni sa recherche. Il lit simplement les métadonnées du fichier.

fseek()/ftell() fonctionne parfois .

 if (fseek(fp, 0L, SEEK_END) != 0) printf("Size: %ld\n", ftell(fp)); } 

Problèmes.

  1. Si la taille du fichier dépasse environ LONG_MAX , la LONG_MAX long int ftell(FILE *stream) est problématique.

  2. Si le fichier est ouvert en mode texte, la valeur ftell() par ftell() peut ne pas correspondre à la longueur du fichier. “Pour un stream de texte, son indicateur de position de fichier contient des informations non spécifiées”, C11dr §7.21.9.4 2

  3. Si le fichier est ouvert en mode binary, fseek(fp, 0L, SEEK_END) n’est pas bien défini. “La définition de l’indicateur de position du fichier sur la fin du fichier, comme avec fseek(file, 0, SEEK_END) , a un comportement indéfini pour un stream binary (en raison de possibles caractères nuls de fin) ou pour tout stream avec un codage dépendant de l’état ne se termine certainement pas dans l’état de décalage initial “. C11dr note de bas de page 268. @Evert Ceci s’applique le plus souvent aux plates-formes antérieures, mais il fait toujours partie des spécifications.

  4. Si le fichier est un stream comme une entrée série ou stdin , fseek(file, 0, SEEK_END) pas de sens.

La solution habituelle pour trouver la taille d’un fichier est une plate-forme non portable spécifique. Exemple bonne réponse @dbush .

Remarque: Si le code tente d’allouer de la mémoire en fonction de la taille du fichier, celle-ci peut facilement être dépassée par la taille du fichier.

En raison de ces problèmes, je ne recommande pas cette approche.

En règle générale, le problème doit être corrigé pour ne pas nécessiter de trouver la taille du fichier, mais pour agrandir les données au fur et à mesure du traitement des entrées.


Clause de non-responsabilité: Notez que les notes de bas de page de la spécification C sont informatives et ne sont donc pas nécessairement normatives .

La meilleure méthode à mon avis est fstat() : https://linux.die.net/man/2/fstat

Eh bien, vous pouvez estimer la taille d’un fichier de plusieurs manières:

  • Vous pouvez read(2) le fichier du début à la fin, et le nombre ou les caractères lus correspondent à la taille du fichier. C’est une façon fastidieuse d’obtenir la taille d’un fichier, car vous devez lire tout le fichier pour en obtenir la taille. Mais si le système d’exploitation ne permet pas de positionner le pointeur de fichier de manière arbitraire, c’est le seul moyen d’obtenir la taille du fichier.
  • Ou vous pouvez déplacer le pointeur à la fin de la position du fichier. C’est le lseek(2) vous avez montré dans la question, mais veillez à ce que vous fassiez l’appel système deux fois , car la valeur renvoyée correspond à la position réelle avant de déplacer le pointeur à l’endroit souhaité.
  • Ou vous pouvez utiliser l’appel système stat(2) , qui vous indiquera toutes les informations administratives du fichier, telles que le propriétaire, le groupe, les permissions, la taille , le nombre de blocs occupés par le fichier dans le disque, le disque auquel ce fichier appartient, nombre d’entrées de répertoire pointant dessus, etc. Cela vous permet d’obtenir toutes ces informations avec un seul appel système .

D’autres méthodes que vous ftell(3) (comme l’utilisation de l’appel de la ftell(3) stdio) fonctionneront également (avec le même problème, il en résulte deux appels système pour définir et récupérer / restaurer le pointeur de fichier), mais pose le problème de l’implication de bibliothèques. que vous n’utilisez probablement pas pour autre chose. Il devrait être compliqué d’obtenir un pointeur FILE * (par exemple, fdopen(3) ) sur un descripteur de fichier int , juste pour pouvoir utiliser la fonction ftell(3) dessus (deux fois), puis le fclose(3) .