Comment puis-je connaître la taille d'un fichier, en octets ?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
Comment puis-je connaître la taille d'un fichier, en octets ?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
Sur les systèmes de type Unix, vous pouvez utiliser les appels système POSIX : stat
sur un chemin ou fstat
sur un descripteur de fichier déjà ouvert (POSIX page de manuel Linux page de manuel ).
(Obtenir un descripteur de fichier à partir de open(2)
ou fileno(FILE*)
sur un flux stdio).
Basé sur le code de 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;
}
Changements :
const char
.struct stat
qui n'avait pas le nom de la variable.-1
en cas d'erreur, au lieu de 0
ce qui serait ambigu pour un fichier vide. off_t
est un type signé, ce qui est donc possible.Si vous voulez fsize()
pour imprimer un message en cas d'erreur, vous pouvez utiliser ceci :
#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;
}
Sur les systèmes 32 bits, vous devez le compiler avec l'option -D_FILE_OFFSET_BITS=64
sinon off_t
ne pourra contenir que des valeurs allant jusqu'à 2 Go. Consultez la section "Utilisation de LFS" de Support des gros fichiers sous Linux pour les détails.
C'est spécifique à Linux/Unix - cela vaut la peine de le préciser puisque la question ne spécifiait pas de système d'exploitation.
Vous pourriez probablement changer le type de retour en ssize_t et convertir la taille à partir d'un off_t sans problème. Il semblerait plus logique d'utiliser un ssize_t :-) (À ne pas confondre avec size_t qui est non signé et ne peut être utilisé pour indiquer une erreur).
N'utilisez pas int
. Les fichiers de plus de 2 gigaoctets sont monnaie courante de nos jours.
N'utilisez pas unsigned int
. Les fichiers de plus de 4 gigaoctets sont courants, tout comme certaines saletés un peu moins courantes.
IIRC la bibliothèque standard définit off_t
comme un entier 64 bits non signé, ce qui est ce que tout le monde devrait utiliser. Nous pourrons le redéfinir en 128 bits dans quelques années, lorsque nous commencerons à avoir des fichiers de 16 exaoctets.
Si vous êtes sous Windows, vous devriez utiliser GetFileSizeEx - il utilise en fait un entier 64 bits signé, donc ils vont commencer à avoir des problèmes avec des fichiers de 8 exabytes. Stupide Microsoft ! :-)
J'ai utilisé des compilateurs où off_t est en 32 bits. Bien sûr, c'est sur des systèmes embarqués où les fichiers de 4GB sont moins courants. Quoi qu'il en soit, POSIX définit également off64_t et les méthodes correspondantes pour ajouter à la confusion.
J'aime toujours les réponses qui supposent Windows et ne font rien d'autre que critiquer la question. Pourriez-vous ajouter quelque chose qui soit conforme à POSIX ?
@JL2210 la réponse acceptée de Ted Percival montre une solution conforme à Posix, donc je ne vois pas l'intérêt de répéter l'évidence. J'ai (et 70 autres) pensé que l'ajout de la note concernant Windows et la non-utilisation d'entiers 32 bits signés pour représenter les tailles de fichiers était une valeur ajoutée en plus de cela. Au revoir
La solution de Matt devrait fonctionner, sauf qu'il s'agit de C++ au lieu de C, et que le tell initial ne devrait pas être nécessaire.
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;
}
J'ai aussi corrigé votre accolade pour vous ;)
Mise à jour : Ce n'est pas vraiment la meilleure solution. Elle est limitée aux fichiers de 4GB sous Windows et elle est probablement plus lente que l'utilisation d'un appel spécifique à la plateforme comme GetFileSizeEx
o stat64
.
Oui, vous devriez. Cependant, à moins qu'il n'y ait une raison vraiment impérieuse de ne pas écrire spécifique à la plate-forme, vous devriez probablement juste utiliser un appel spécifique à la plate-forme plutôt que le modèle ouverture/cherche-fin/appel/fermeture.
Désolé pour la réponse tardive, mais j'ai un problème majeur ici. L'application se bloque lorsqu'elle accède à des fichiers restreints (comme les fichiers protégés par un mot de passe ou les fichiers système). Existe-t-il un moyen de demander un mot de passe à l'utilisateur lorsque cela est nécessaire ?
@Justin, vous devriez probablement ouvrir une nouvelle question spécifique au problème que vous rencontrez, et fournir des détails sur la plate-forme sur laquelle vous êtes, comment vous accédez aux fichiers, et quel est le comportement.
**Ne faites pas cela ( Pourquoi ? ) :
Je cite le document standard C99 que j'ai trouvé en ligne : "Définir l'indicateur de position de fichier à la fin du fichier, comme avec
fseek(file, 0, SEEK_END)
a un comportement non défini pour un flux binaire (en raison de la possibilité de caractères nuls à la fin) ou pour tout flux dont le codage dépend de l'état et qui ne se termine pas assurément dans l'état de décalage initial**.
Changez la définition en int pour que les messages d'erreur puissent être transmis, puis utilisez fseek()
y ftell()
pour déterminer la taille du fichier.
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
}
@mezhaka : Ce rapport du CERT est tout simplement faux. fseeko
y ftello
(ou fseek
y ftell
si vous n'avez pas le choix et que vous êtes satisfait des limites de taille de fichier avec lesquelles vous pouvez travailler) sont la manière correcte de déterminer la longueur d'un fichier. stat
-solutions basées sur la technologie ne fonctionnent pas sur de nombreux "fichiers" (tels que les périphériques de bloc) et ne sont pas portables sur des systèmes non-POSIX-ish.
C'est la seule façon d'obtenir la taille du fichier sur de nombreux systèmes non conformes à POSIX (comme mon très minimaliste mbed).
Vous ne voulez absolument pas utiliser int
ici. ftell
renvoie un message signé long
qui est un type 64 bits sur de nombreux systèmes 64 bits (mais pas tous). Il n'est toujours que 32 bits sur la plupart des systèmes 32 bits, et vous devez donc ftello
avec off_t
pour être en mesure de traiter des fichiers volumineux de manière portative. Bien que l'ISO C ait choisi de ne pas définir ce comportement, la plupart des implémentations le font, ce qui fait que cela fonctionne en pratique sur la plupart des systèmes.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
0 votes
Vous allez devoir utiliser une fonction de bibliothèque pour récupérer les détails d'un fichier. Comme le C est complètement indépendant de la plate-forme, vous devrez nous dire pour quelle plate-forme/système d'exploitation vous développez !
1 votes
Pourquoi
char* file
Pourquoi pas ?FILE* file
? -10 votes
@user12211554 pour que... juste...
strlen
¡!1 votes
Notez que : le fichier peut croître entre
fsize
yread
. Faites attention.