Comment obtenir la taille du fichier en C ANSI, sans fseek et ftell?
Alors que la recherche de façons de trouver la taille d'un fichier donné un FILE*
, je suis tombé sur cet article conseiller contre elle. Au lieu de cela, il semble encourager l'utilisation de descripteurs de fichier et fstat
.
Cependant, j'étais sous l'impression que fstat
, open
et les descripteurs de fichiers, en général, ne sont pas aussi portable (Après un peu de recherche, j'ai trouvé quelque chose à ce effet).
Est-il un moyen pour obtenir la taille d'un fichier en C ANSI, tout en gardant en ligne avec les mises en garde dans l'article?
Veuillez noter que l'article que vous avez associé est Considéré comme Nocif.
Il n'est pas utile, mais... ouvrir un fichier en mode ajout d'œuvres: FILE* fp = fopen("teste.txt",""); size_t sz = ftell(fp);
fseek
/ftell
(en fait fseeko
/ftello
, si vous avez POSIX, de sorte que vous pouvez traiter de gros fichiers) est la meilleure façon de déterminer la taille du fichier. Le stat
de remplacement échoue pour déterminer les tailles de certains non-régulier-fichiers bien défini tailles, tels que les périphériques de bloc (des partitions de disque, etc.).Il n'est pas utile, mais... ouvrir un fichier en mode ajout d'œuvres: FILE* fp = fopen("teste.txt",""); size_t sz = ftell(fp);
OriginalL'auteur math4tots | 2012-03-22
Vous devez vous connecter pour publier un commentaire.
En C standard, le
fseek
/ftell
la danse est à peu près le seul jeu en ville. Ce que vous voulez faire dépend au moins d'une certaine façon sur l'environnement spécifique de votre programme s'exécute. Malheureusement, dit danse aussi a ses problèmes comme décrit dans les articles que vous avez lié.Je pense que l'on peut toujours lire tout le fichier jusqu'à ce que les expressions du FOLKLORE et de garder trace le long de la route - avec
fread()
par exemple.Je pense que la réponse a été downvoted en raison de la formulation de la norme, qui, au moins si j'ai été mentionnés:
Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state.
etA binary stream need not meaningfully support fseek calls with a whence value of SEEK_END.
.. et c'est aussi dans ma réponse.
Notez que si l'ISO C n'a pas de définir la fin d'un fichier binaire, POSIX, et tous le monde réel, post-1980 implémentations de C d'accord sur cette question. Les fichiers binaires ont une taille exacte et vous pouvez demander par rapport à la fin.
Mais en utilisant les fonctions POSIX est un comportement indéfini selon C. Il n'y a pas de solution pour un comportement non défini dans la résolution de ce problème.
fseek
à l'aide deSEEK_END
est un comportement indéfini, et l'appel d'une fonction qui n'est pas dans la norme ISO C et pas dans votre programme est un comportement indéfini. La résolution de ce problème, et la plupart des autres problèmes de la vie quotidienne, il faut supprimer les ISO C œillères des yeux.OriginalL'auteur Carl Norum
L'article prétend
fseek(stream, 0, SEEK_END)
est un comportement indéterminé en citant un hors contexte, note de bas de page.La note de bas de page s'affiche en texte sur le large orientée flux, qui sont des cours d'eau que la première opération effectuée sur eux, c'est une opération sur une large personnages.
Ce comportement indéfini découle de la combinaison de deux paragraphes. Premier §7.19.2/5 dit:
Et les restrictions de positionnement dans le fichier avec le texte des ruisseaux (§7.19.9.2/4) sont:
Ce fait
fseek(stream, 0, SEEK_END)
comportement indéfini de large orientée flux. Il n'y a aucune règle de ce type, comme §7.19.2/5 pour octets orienté flux.En outre, lorsque la norme dit:
Cela ne veut pas dire que c'est un comportement indéterminé de le faire. Mais si le flux de données prend en charge, c'est ok.
Apparemment, cela existe pour permettre à des fichiers binaires peuvent avoir grossière de la taille de la granularité, c'est à dire pour la taille à être un certain nombre de secteurs de disque plutôt que d'un nombre d'octets, et en tant que tel permet pour un nombre quelconque de zéros apparaissent comme par magie à la fin des fichiers binaires.
SEEK_END
ne peut pas être sérieusement pris en charge dans ce cas. D'autres exemples comprennent des tuyaux ou infini de fichiers comme/dev/zero
. Cependant, la norme ne fournit aucun moyen de distinguer entre de tels cas, si vous êtes coincé avec dépendant du système d'appels si vous voulez considérer qu'.Le dernier paragraphe n'est pas tout à fait droit. C ISO permet aux fichiers binaires d'avoir entendu de la taille de la granularité, c'est à dire pour la taille à être un certain nombre de secteurs de disque plutôt que d'un nombre d'octets, et en tant que tel permet pour un nombre quelconque de zéros apparaissent comme par magie à la fin des fichiers binaires. C'est la raison pour
SEEK_END
ne peut pas être "de façon significative" pris en charge. Encore, pas de monde réel de la mise en œuvre serait ce brisé; de plus, POSIX interdit.Oh, merci. Ce serait en effet assez bizarre. Ces valeurs null à la fin être lu par dire
fread
?L'article ne cite pas un dehors du contexte de la note de bas de page; il cite une pertinente foonote. La base de revendications dans l'article sont basées sur le texte normatif. L'auteur de l'article prend texte normatif et de la notion de comportement indéfini d'un rationnel contexte, et ne réalise pas que la solution proposée (l'utilisation de la plate-forme des fonctions spécifiques, ne sont pas définis dans le programme C ou de la bibliothèque standard) sont, formellement, un comportement indéfini.
OriginalL'auteur R. Martinho Fernandes
Utilisation fstat - le descripteur de fichier - peut obtenir que de fileno de la
FILE*
- d'Où la taille est dans vos mains le long de avec d'autres détails.c'est à dire
Où
filePointer
est leFILE *
et
buf
estComme une affiche précédente a noté l'OS différents, mais la même chose est disponible par windows. L'équivalent de
fstat
est disponible.Suppose que la meilleure option est de le faire fonctionner selon le système d'exploitation.
Voté parce que c'est la norme POSIX.
Danger, Will Robinson! Si vous utilisez
fstat()
sur un fichier ouvert à qui vous avez déjà écrit des trucs via unFILE*
il pourrait bien retourner la mauvaise taille, en raison de tampon de données pas encore été écrite.OriginalL'auteur Ed Heal
différents OS est de fournir des api différentes pour cela. Par exemple, dans windows, nous avons:
GetFileAttributes()
Dans MAC, nous avons:
[[[NSFileManager defaultManager] attributesOfItemAtPath:someFilePath erreur:nil] fileSize];
Mais raw méthode est uniquement par fread et fseek seulement:
Comment puis-je obtenir un fichier de taille en C?
OriginalL'auteur user739711
Vous ne pouvez pas toujours éviter d'écrire de la plate-forme de code spécifiques, en particulier lorsque vous avez à traiter avec les choses qui sont fonction de la plate-forme. Les tailles de fichiers sont une fonction du système de fichiers, donc en règle générale, je voudrais utiliser le système de fichiers natif API pour obtenir ces informations sur le fseek/ftell de la danse. J'aimerais créer mon propre générique wrapper autour d'elle, afin de ne pas polluer la logique de l'application avec la plate-forme et les détails spécifiques à rendre le code plus facile de port.
OriginalL'auteur John Bode
Le résumé est que vous doit utiliser fseek/ftell parce qu'il n'y a pas d'alternative (même la mise en œuvre spécifique) qui est mieux.
La question sous-jacente est que la "taille" d'un fichier en octets n'est pas toujours la même que la longueur des données dans le fichier et que, dans certains cas, la longueur des données n'est pas disponible.
Une POSIX exemple de ce qui se passe lorsque vous écrivez des données sur un périphérique, le système d'exploitation ne connaît que la taille de l'appareil. Une fois que les données ont été écrites et l' (FILE*) fermé il n'y est fait aucune mention de la longueur des données écrites. Si l'appareil est ouvert pour la lecture de la fseek/ftell approche va échouer ou vous donner la taille de l'ensemble du dispositif.
Lorsque le C ANSI comité était assis à la fin des années 1980, un certain nombre de systèmes d'exploitation les membres de la rappeler simplement ne pas stocker la longueur des données dans un fichier; au contraire, ils stockés blocs du disque le fichier et à supposer que quelque chose dans les données résilié. Le "texte" stream représente cette. L'ouverture d'un 'binaire' stream sur ces fichiers ne montre pas seulement la magie octet de terminaison, mais aussi tous les octets au-delà qui n'ont jamais été écrit, mais arriver à être dans le même bloc de disque.
Par conséquent, le C-90 norme a été rédigée de manière à est valide pour utiliser le fseek truc; le résultat est conforme au programme, mais le résultat peut ne pas être ce que vous attendez. Le comportement de ce programme n'est pas "undefined" dans le C-90 définition et il n'est pas "la mise en œuvre définies" (en raison de l'ONU*X, il varie avec le fichier). Ni est-il 'invalide'. Plutôt, vous obtenez un numéro que vous ne pouvez pas compter entièrement sur ou, peut-être, en fonction des paramètres de fseek, -1 et errno.
Dans la pratique, si la ruse réussit, vous obtenez un nombre qui comprend au moins toutes les données, et c'est probablement ce que vous voulez, et si le truc d'échec, il est presque certainement quelqu'un d'autre à blâmer.
John Bowler
OriginalL'auteur John Bowler
L'article a un petit problème de logique.
(Correctement) l'identifie à une certaine utilisation de fonctions C a un comportement qui n'est pas définie par la norme ISO C. Mais alors, pour éviter ce comportement indéfini, l'article propose une solution: remplacer l'utilisation de la plate-forme à des fonctions spécifiques. Malheureusement, l'utilisation de la plate-forme des fonctions spécifiques est undefined aussi selon la norme ISO C. par conséquent, le conseil ne permet pas de résoudre le problème de comportement indéfini.
La citation dans mon exemplaire de 1999 de la norme confirme que le prétendu comportement est en effet pas défini:
Mais un comportement indéfini ne veut pas dire "mauvais comportement", c'est tout simplement le comportement pour lequel la norme ISO C standard ne donne aucune définition. Pas tous les comportements indéfinis sont les mêmes.
Certains comportements indéfinis sont des domaines dans la langue où significative des extensions peuvent être fournis. La plate-forme comble le vide par la définition d'un comportement.
Offrir un lieu de travail
fseek
qui peuvent solliciter à partir deSEEK_END
est un exemple d'une extension à la place de comportement indéfini. Il est possible de confirmer si oui ou non une plate-forme prend en chargefseek
deSEEK_END
, et si cela est mis en service, il est bien d'utiliser.Fournir une fonction distincte comme
lseek
est également une extension à la place de comportement indéfini (comportement indéfini de l'appel d'une fonction qui n'est pas dans la norme ISO C et n'est pas définie dans le programme C). C'est bien de l'utiliser, si disponible.Noter que ces plates-formes qui ont des fonctions comme la POSIX
lseek
seront également susceptibles d'avoir un ISO Cfseek
les œuvres deSEEK_END
. Notez également que sur les plates-formes oùfseek
sur un fichier binaire ne peut pas demander àSEEK_END
, qui est probablement la raison en est que c'est impossible à faire (pas d'API peuvent être fournis de le faire et c'est pourquoi la fonction de la bibliothèque Cfseek
n'est pas en mesure de le soutenir).Donc, si
fseek
fournit le comportement désiré sur la plate-forme donnée, rien ne doit être fait pour le programme; c'est une perte de temps pour changer d'utiliser cette plate-forme spéciale de fonction. D'autre part, sifseek
ne fournit pas le comportement, puis probablement rien, de toute façon.Noter que, même en incluant un en-tête non standard qui n'est pas dans le programme est un comportement indéfini. (Par omission de la définition de comportement.) Par exemple, si celui-ci apparaît dans un programme C:
le comportement n'est pas défini par la suite. [Voir les Références ci-dessous.] Le comportement de la prétraitement directive
#include
est défini, bien sûr. Mais cela crée deux possibilités: soit l'en-tête<unistd.h>
n'existe pas, dans ce cas, un diagnostic est nécessaire. Ou l'en-tête n'existe pas. Mais dans ce cas, le contenu ne sont pas connus (aussi loin que la norme ISO C est concerné; rien de tel en-tête est documenté pour la Bibliothèque). Dans ce cas, la directive include apporte un inconnu morceau de code, en l'intégrant dans l'unité de traduction. Il est impossible de définir le comportement d'un inconnu morceau de code.#include <platform-specific-header.h>
est l'un des échapper à trappes dans la langue pour faire quoi que ce soit sur une plate-forme donnée.En forme de point:
<unistd.h>
. Un indéfini ISO programme C peut être bien définie POSIX programme C.Références:
#include <pascal.h>
peut apporter dans un mot clé pascal pour le lien.] http://groups.google.com/group/comp.lang.c/msg/e2762cfa9888d5c6?dmode=sourceJe pense que vous mélangez "un comportement indéfini" et "la mise en œuvre définies dans le comportement".
de Martel, pour la deuxième fois.
Vraiment, je pense que le problème est à propos de quoi "un comportement indéterminé' s'applique à: le compilateur du comportement est très bien définie pour le traitement comprend l'. Le programme qui en résulte évidemment peut avoir un comportement indéterminé (l'enfer, il pourrait même être mal formé). Généralement 'comportement indéfini" désigne le compilateur actions/de sortie. Pas le comportement du programme qui en résulte (même si, bien sûr, qu'il devient difficile de raisonner sur ce, au moment même)
Non, "un comportement indéfini" signifie tout simplement en toute situation pour laquelle le langage de programmation standard, soit dit qu'il a "un comportement indéfini", ou pour lesquels il ne dispose d'aucune définition de comportement. Il ne signifie pas "non défini par n'importe quel système ou le fournisseur". Il signifie ce n'est pas la norme définie par. Un compilateur comportement n'est pas très bien standard défini par! La norme C que partiellement définit ce qui arrive quand
#include <unistd.h>
est traitée. Pas assez pour réellement définir les conséquences.OriginalL'auteur Kaz