Vous allez devoir utiliser une fonction de bibliothèque pour récupérer les détails d'un fichier. Comme C est complètement indépendant de la plate-forme, vous devrez nous indiquer pour quelle plate-forme / système d'exploitation vous développez!
Chris Roberts du
Pourquoi char* file, pourquoi pas FILE* file? -1
Mr Oscar le
-1 parce que les fonctions de fichiers doivent accepter les descripteurs de fichiers et non les chemins de fichiers
M. Oscar
Réponses:
144
Basé sur le code de NilObject:
#include<sys/stat.h>#include<sys/types.h>off_t fsize(constchar*filename){struct stat st;if(stat(filename,&st)==0)return st.st_size;return-1;}
Changements:
Faites de l'argument de nom de fichier un const char.
Correction de la struct statdéfinition, qui manquait le nom de la variable.
Renvoie -1sur erreur au lieu de 0, ce qui serait ambigu pour un fichier vide. off_test un type signé, c'est donc possible.
Si vous souhaitez fsize()imprimer un message 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(constchar*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_tne contiendra que des valeurs jusqu'à 2 Go. Consultez la section «Utilisation de LFS» de la prise en charge des fichiers volumineux sous Linux pour plus de détails.
Ceci est spécifique à Linux / Unix - il vaut probablement la peine de le souligner puisque la question ne spécifiait pas de système d'exploitation.
Drew Hall
1
Vous pourriez probablement changer le type de retour en ssize_t et convertir la taille d'un off_t sans aucun problème. Il semble plus judicieux d'utiliser un ssize_t :-) (à ne pas confondre avec size_t qui n'est pas signé et ne peut pas être utilisé pour indiquer une erreur.)
Ted Percival
1
Pour un code plus portable, utilisez fseek+ ftellcomme proposé par Derek.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
9
Pour un code plus portable, utilisez fseek+ ftellcomme proposé par Derek. Non . La norme C précise que fseek()pour SEEK_ENDun fichier binaire est un comportement non défini. 7.19.9.2 La fseekfonction ... Un flux binaire n'a pas besoin de prendre en charge de manière significative les fseekappels avec une valeur SEEK_ENDwhence de , et comme indiqué ci-dessous, qui provient de la note 234 à la p. 267 de la norme lié par C, et qui en particulier des étiquettes fseekpour SEEK_ENDun flux binaire en tant que comportement non défini. .
Andrew Henle
74
N'utilisez pas int. Les fichiers de plus de 2 gigaoctets sont courants comme de la saleté de nos jours
N'utilisez pas unsigned int. Les fichiers de plus de 4 gigaoctets sont courants en tant que saleté légèrement moins courante
IIRC, la bibliothèque standard définit off_tcomme un entier 64 bits non signé, ce que tout le monde devrait utiliser. Nous pouvons redéfinir cela à 128 bits dans quelques années lorsque nous commencerons à avoir 16 fichiers exaoctets qui traînent.
Si vous êtes sous Windows, vous devez utiliser GetFileSizeEx - il utilise en fait un entier 64 bits signé, de sorte qu'ils commenceront à rencontrer des problèmes avec 8 fichiers exaoctets. Microsoft stupide! :-)
J'ai utilisé des compilateurs où off_t vaut 32 bits. Certes, c'est sur les systèmes embarqués où les fichiers de 4 Go sont moins courants. Quoi qu'il en soit, POSIX définit également off64_t et les méthodes correspondantes pour ajouter à la confusion.
Aaron Campbell
J'aime toujours les réponses qui supposent Windows et ne font rien d'autre que critiquer la question. Pourriez-vous s'il vous plaît ajouter quelque chose qui est compatible POSIX?
SS Anne
1
@ JL2210 la réponse acceptée de Ted Percival montre une solution conforme posix, donc je ne vois aucun sens à répéter l'évidence. Je (et 70 autres) pensais que l'ajout de la note sur les fenêtres et de ne pas utiliser d'entiers 32 bits signés pour représenter la taille des fichiers était une valeur ajoutée en plus de cela. Cheers
Orion Edwards
30
La solution de Matt devrait fonctionner, sauf que c'est C ++ au lieu de C, et le tell initial ne devrait pas être nécessaire.
unsignedlong fsize(char* file){FILE* f = fopen(file,"r");
fseek(f,0, SEEK_END);unsignedlong len =(unsignedlong)ftell(f);
fclose(f);return len;}
Correction de votre attelle pour vous aussi. ;)
Mise à jour: ce n'est pas vraiment la meilleure solution. Il est limité à 4 Go de fichiers sur Windows et il est probablement plus lent que d'utiliser simplement un appel spécifique à la plate-forme comme GetFileSizeExou stat64.
Oui tu devrais. Cependant, à moins qu'il n'y ait une raison vraiment convaincante de ne pas écrire spécifique à la plate-forme, vous devriez probablement utiliser un appel spécifique à la plate-forme plutôt que le modèle open / seek-end / tell / close.
Derek Park
1
Désolé pour la réponse tardive, mais j'ai un problème majeur ici. Cela provoque le blocage de l'application lors de l'accès à des fichiers restreints (comme des fichiers protégés par mot de passe ou système). Existe-t-il un moyen de demander à l'utilisateur un mot de passe en cas de besoin?
Justin
@Justin, vous devriez probablement ouvrir une nouvelle question spécifiquement sur le problème que vous rencontrez, et fournir des détails sur la plate-forme sur laquelle vous vous trouvez, comment vous accédez aux fichiers et quel est le comportement.
Derek Park
1
Les deux C99 et C11 reviennent long intde ftell(). (unsigned long)la coulée n'améliore pas la portée car déjà limitée par la fonction. ftell()retourne -1 en cas d'erreur et qui est obscurcie avec la distribution. Suggérer de fsize()renvoyer le même type que ftell().
chux
Je suis d'accord. Le casting devait correspondre au prototype original dans la question. Je ne me souviens pas pourquoi je l'ai transformé en unsigned long au lieu de unsigned int, cependant.
Citant le document standard C99 que j'ai trouvé en ligne: «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 flux binaire (en raison de possibles caractères nulles de fin) ou pour tout flux avec un codage dépendant de l'état qui ne se termine pas assurément dans l'état de décalage initial. **
Modifiez la définition en int afin que les messages d'erreur puissent être transmis, puis utilisez fseek()et ftell()pour déterminer la taille du fichier.
@mezhaka: Ce rapport CERT est tout simplement faux. fseekoet ftello(ou fseeket ftellsi vous êtes bloqué sans l'ancien et satisfait des limites de taille de fichier avec lesquelles vous pouvez travailler) sont la bonne façon de déterminer la longueur d'un fichier. statLes solutions basées sur les fichiers 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.
R .. GitHub STOP AIDER ICE
1
C'est le seul moyen d'obtenir la taille du fichier sur de nombreux systèmes non compatibles posix (comme mon mbed très minimaliste)
Earlz
9
POSIX
Le standard POSIX a sa propre méthode pour obtenir la taille du fichier.
Incluez l'en- sys/stat.htête pour utiliser la fonction.
Synopsis
Obtenez des statistiques de fichiers à l'aide de stat(3).
Obtenez la st_sizepropriété.
Exemples
Remarque : il limite la taille à 4GB. Si ce n'est pas le Fat32système de fichiers, utilisez la version 64 bits!
#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)
L' ANSI C ne fournit pas directement le moyen de déterminer la longueur du fichier.
Nous devrons utiliser notre esprit. Pour l'instant, nous allons utiliser l'approche de recherche!
Synopsis
Recherchez le fichier jusqu'à la fin en utilisant fseek(3).
Obtenez la position actuelle en utilisant ftell(3).
Exemple
#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",(unsignedlong)f_size);}
Si le fichier est stdinou un tube. POSIX, ANSI C ne fonctionnera pas.
Il retournera 0si le fichier est un tube ou stdin.
Opinion : Vous devriez utiliser le standard POSIX à la place. Parce qu'il prend en charge 64 bits.
Et si vous créez une application Windows, utilisez l' API GetFileSizeEx car les E / S de fichier CRT sont compliquées , en particulier pour déterminer la longueur de fichier, en raison des particularités des représentations de fichiers sur différents systèmes;)
Ce n'est pas le standard C. Cela fait partie du standard POSIX, mais pas du standard C.
Derek Park
3
Une recherche rapide dans Google a trouvé une méthode utilisant fseek et ftell et un fil avec cette question avec des réponses que cela ne peut pas être fait en C d'une autre manière.
Vous pouvez utiliser une bibliothèque de portabilité comme NSPR (la bibliothèque qui alimente Firefox) ou vérifier son implémentation (plutôt poilue).
J'ai utilisé cet ensemble de code pour trouver la longueur du fichier.
//opens a file with a file descriptorFILE* i_file;
i_file = fopen(source,"r");//gets a long from the file descriptor for fstatlong f_d = fileno(i_file);struct stat buffer;
fstat(f_d,&buffer);//stores file sizelong file_length = buffer.st_size;
fclose(i_file);
Ce que cela fait, c'est d'abord chercher la fin du fichier; puis, indiquez où se trouve le pointeur de fichier. Enfin (c'est facultatif), il revient au début du fichier. Notez que cela fpdevrait être un flux binaire.
file_size contient le nombre d'octets que contient le fichier. Notez que puisque (selon climits.h) le type long non signé est limité à 4294967295 octets (4 gigaoctets), vous devrez trouver un type de variable différent si vous êtes susceptible de traiter des fichiers plus volumineux que cela.
En quoi est-ce différent de la réponse de Derek d'il y a 8 ans?
PP
C'est un comportement indéfini pour un flux binaire et pour un flux de texte, ftellil ne renvoie pas de valeur représentative du nombre d'octets pouvant être lus à partir du fichier.
Andrew Henle
0
J'ai une fonction qui fonctionne bien uniquement avec stdio.h. Je l'aime beaucoup et cela fonctionne très bien et est assez concis:
ftellattend un descripteur de fichier, pas un nom de fichier, comme argument.
Barmar le
@Barmar, No ftelln'attend pas de descripteur de fichier, il en attend un à la FILE*place. Consultez d'abord la page de manuel!
L'approche est complètement fausse, c'est une constante qui ftellreviendrait à 0chaque fois!
Cette réponse est complètement fausse, car pour une, vous devez d' fseek()abord utiliser pour rechercher la fin du fichier, et aussi, ftell()attend une FILE *, pas une chaîne! Vous seriez bien servi pour étoffer votre réponse.
char* file
, pourquoi pasFILE* file
? -1Réponses:
Basé sur le code de NilObject:
Changements:
const char
.struct stat
définition, qui manquait le nom de la variable.-1
sur erreur au lieu de0
, ce qui serait ambigu pour un fichier vide.off_t
est un type signé, c'est donc possible.Si vous souhaitez
fsize()
imprimer un message d'erreur, vous pouvez utiliser ceci:Sur les systèmes 32 bits, vous devez le compiler avec l'option
-D_FILE_OFFSET_BITS=64
, sinonoff_t
ne contiendra que des valeurs jusqu'à 2 Go. Consultez la section «Utilisation de LFS» de la prise en charge des fichiers volumineux sous Linux pour plus de détails.la source
fseek
+ftell
comme proposé par Derek.fseek
+ftell
comme proposé par Derek. Non . La norme C précise quefseek()
pourSEEK_END
un fichier binaire est un comportement non défini. 7.19.9.2 Lafseek
fonction ... Un flux binaire n'a pas besoin de prendre en charge de manière significative lesfseek
appels avec une valeurSEEK_END
whence de , et comme indiqué ci-dessous, qui provient de la note 234 à la p. 267 de la norme lié par C, et qui en particulier des étiquettesfseek
pourSEEK_END
un flux binaire en tant que comportement non défini. .N'utilisez pas
int
. Les fichiers de plus de 2 gigaoctets sont courants comme de la saleté de nos joursN'utilisez pas
unsigned int
. Les fichiers de plus de 4 gigaoctets sont courants en tant que saleté légèrement moins couranteIIRC, la bibliothèque standard définit
off_t
comme un entier 64 bits non signé, ce que tout le monde devrait utiliser. Nous pouvons redéfinir cela à 128 bits dans quelques années lorsque nous commencerons à avoir 16 fichiers exaoctets qui traînent.Si vous êtes sous Windows, vous devez utiliser GetFileSizeEx - il utilise en fait un entier 64 bits signé, de sorte qu'ils commenceront à rencontrer des problèmes avec 8 fichiers exaoctets. Microsoft stupide! :-)
la source
La solution de Matt devrait fonctionner, sauf que c'est C ++ au lieu de C, et le tell initial ne devrait pas être nécessaire.
Correction de votre attelle pour vous aussi. ;)
Mise à jour: ce n'est pas vraiment la meilleure solution. Il est limité à 4 Go de fichiers sur Windows et il est probablement plus lent que d'utiliser simplement un appel spécifique à la plate-forme comme
GetFileSizeEx
oustat64
.la source
long int
deftell()
.(unsigned long)
la coulée n'améliore pas la portée car déjà limitée par la fonction.ftell()
retourne -1 en cas d'erreur et qui est obscurcie avec la distribution. Suggérer defsize()
renvoyer le même type queftell()
.** Ne faites pas ça ( pourquoi? ):
Modifiez la définition en int afin que les messages d'erreur puissent être transmis, puis utilisez
fseek()
etftell()
pour déterminer la taille du fichier.la source
fseeko
etftello
(oufseek
etftell
si vous êtes bloqué sans l'ancien et satisfait des limites de taille de fichier avec lesquelles vous pouvez travailler) sont la bonne façon de déterminer la longueur d'un fichier.stat
Les solutions basées sur les fichiers 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.POSIX
Le standard POSIX a sa propre méthode pour obtenir la taille du fichier.
Incluez l'en-
sys/stat.h
tête pour utiliser la fonction.Synopsis
stat(3)
.st_size
propriété.Exemples
Remarque : il limite la taille à
4GB
. Si ce n'est pas leFat32
système de fichiers, utilisez la version 64 bits!ANSI C (standard)
L' ANSI C ne fournit pas directement le moyen de déterminer la longueur du fichier.
Nous devrons utiliser notre esprit. Pour l'instant, nous allons utiliser l'approche de recherche!
Synopsis
fseek(3)
.ftell(3)
.Exemple
la source
struct _stat64
et__stat64()
pour _Windows.Et si vous créez une application Windows, utilisez l' API GetFileSizeEx car les E / S de fichier CRT sont compliquées , en particulier pour déterminer la longueur de fichier, en raison des particularités des représentations de fichiers sur différents systèmes;)
la source
Si vous êtes d'accord avec l'utilisation de la bibliothèque std c:
la source
Une recherche rapide dans Google a trouvé une méthode utilisant fseek et ftell et un fil avec cette question avec des réponses que cela ne peut pas être fait en C d'une autre manière.
Vous pouvez utiliser une bibliothèque de portabilité comme NSPR (la bibliothèque qui alimente Firefox) ou vérifier son implémentation (plutôt poilue).
la source
J'ai utilisé cet ensemble de code pour trouver la longueur du fichier.
la source
Essaye ça --
Ce que cela fait, c'est d'abord chercher la fin du fichier; puis, indiquez où se trouve le pointeur de fichier. Enfin (c'est facultatif), il revient au début du fichier. Notez que cela
fp
devrait être un flux binaire.file_size contient le nombre d'octets que contient le fichier. Notez que puisque (selon climits.h) le type long non signé est limité à 4294967295 octets (4 gigaoctets), vous devrez trouver un type de variable différent si vous êtes susceptible de traiter des fichiers plus volumineux que cela.
la source
ftell
il ne renvoie pas de valeur représentative du nombre d'octets pouvant être lus à partir du fichier.J'ai une fonction qui fonctionne bien uniquement avec
stdio.h
. Je l'aime beaucoup et cela fonctionne très bien et est assez concis:la source
Voici une fonction simple et propre qui renvoie la taille du fichier.
la source
Vous pouvez ouvrir le fichier, aller à 0 offset relatif à partir du bas du fichier avec
la valeur renvoyée par fseek est la taille du fichier.
Je n'ai pas codé en C pendant longtemps, mais je pense que cela devrait fonctionner.
la source
En regardant la question,
ftell
peut facilement obtenir le nombre d'octets.la source
ftell
attend un descripteur de fichier, pas un nom de fichier, comme argument.ftell
n'attend pas de descripteur de fichier, il en attend un à laFILE*
place. Consultez d'abord la page de manuel!ftell
reviendrait à0
chaque fois!fseek()
abord utiliser pour rechercher la fin du fichier, et aussi,ftell()
attend uneFILE *
, pas une chaîne! Vous seriez bien servi pour étoffer votre réponse.