Nous avons eu une discussion ici au travail pour savoir pourquoi fread et fwrite prennent une taille par membre et comptent et renvoient le nombre de membres lus / écrits plutôt que de simplement prendre un tampon et une taille. La seule utilisation que nous pourrions trouver est si vous voulez lire / écrire un tableau de structures qui ne sont pas uniformément divisibles par l'alignement de la plate-forme et qui ont donc été remplies mais qui ne peuvent pas être si courantes pour justifier ce choix dans la conception.
De FREAD (3) :
La fonction fread () lit nmemb éléments de données, chaque taille octets de long, à partir du flux pointé par stream, les stockant à l'emplacement donné par ptr.
La fonction fwrite () écrit nmemb éléments de données, chaque taille octets de long, dans le flux pointé par stream, en les obtenant à partir de l'emplacement donné par ptr.
fread () et fwrite () renvoient le nombre d'éléments lus ou écrits avec succès (c'est-à-dire pas le nombre de caractères). Si une erreur se produit ou si la fin de fichier est atteinte, la valeur de retour est un nombre d'éléments courts (ou zéro).
Réponses:
Il est basé sur la façon dont fread est implémenté.
La spécification UNIX unique dit
fgetc a également cette note:
Bien sûr, cela précède les encodages de caractères fantaisie à octets variables comme UTF-8.
Le SUS note que cela est en fait tiré des documents ISO C.
la source
La différence entre fread (buf, 1000, 1, stream) et fread (buf, 1, 1000, stream) est que dans le premier cas vous n'obtenez qu'un seul morceau de 1000 octets ou nuthin, si le fichier est plus petit et dans le deuxième cas, vous obtenez tout dans le fichier moins de et jusqu'à 1000 octets.
la source
Ce sont de pures spéculations, mais à l'époque (certains sont encore là), de nombreux systèmes de fichiers n'étaient pas de simples flux d'octets sur un disque dur.
De nombreux systèmes de fichiers étaient basés sur des enregistrements, donc pour satisfaire ces systèmes de fichiers de manière efficace, vous devrez spécifier le nombre d'éléments («enregistrements»), permettant à fwrite / fread d'opérer sur le stockage en tant qu'enregistrements, pas seulement en tant que flux d'octets.
la source
Ici, permettez-moi de corriger ces fonctions:
Quant à la justification des paramètres de
fread()
/fwrite()
, j'ai perdu ma copie de K&R il y a longtemps, donc je ne peux que deviner. Je pense qu'une réponse probable est que Kernighan et Ritchie ont peut-être simplement pensé que l'exécution d'E / S binaires se ferait le plus naturellement sur des tableaux d'objets. En outre, ils ont peut-être pensé que les E / S par blocs seraient plus rapides / plus faciles à implémenter ou autre chose sur certaines architectures.Même si la norme C spécifie que
fread()
et doitfwrite()
être mise en œuvre en termes defgetc()
etfputc()
, rappelez-vous que la norme est apparue longtemps après que C a été définie par K&R et que les éléments spécifiés dans la norme n'étaient peut-être pas dans les idées originales des concepteurs. Il est même possible que les choses dites dans "The C Programming Language" de K&R ne soient pas les mêmes que lorsque le langage a été conçu pour la première fois.Enfin, voici ce que PJ Plauger a à dire
fread()
dans "The Standard C Library":Fondamentalement, il dit que
fread()
l'interface est cassée. Carfwrite()
il note que «les erreurs d'écriture sont généralement rares, donc ce n'est pas une lacune majeure» - une affirmation avec laquelle je ne suis pas d'accord.la source
fread(buf, size*n, 1, stream);
si des lectures incomplètes sont une condition d'erreur, il est plus simple de faire en sorte defread
renvoyer simplement 0 ou 1 plutôt que le nombre d'octets lus. Ensuite, vous pouvez faire des choses commeif (!fread(...))
au lieu d'avoir à comparer le résultat avec le nombre d'octets demandé (ce qui nécessite un code C supplémentaire et un code machine supplémentaire).Cela revient probablement à la manière dont les E / S de fichier ont été implémentées. (à l'époque) Il aurait peut-être été plus rapide d'écrire / lire des fichiers dans des blocs que de tout écrire en même temps.
la source
Avoir des arguments séparés pour la taille et le nombre pourrait être avantageux sur une implémentation qui peut éviter de lire des enregistrements partiels. Si l'on utilisait des lectures à un octet à partir de quelque chose comme un tube, même si l'on utilisait des données de format fixe, il faudrait prévoir la possibilité qu'un enregistrement soit divisé en deux lectures. Si pourrait à la place demander, par exemple, une lecture non bloquante de jusqu'à 40 enregistrements de 10 octets chacun lorsqu'il y a 293 octets disponibles, et demander au système de renvoyer 290 octets (29 enregistrements entiers) tout en laissant 3 octets prêts pour la prochaine lecture, ce serait être beaucoup plus pratique.
Je ne sais pas dans quelle mesure les implémentations de fread peuvent gérer une telle sémantique, mais elles pourraient certainement être utiles sur des implémentations qui pourraient promettre de les supporter.
la source
fread(buffer, 10000, 2, stdin)
et que l'utilisateur tape newline-ctrl-D après avoir tapé 18 000 octets, ce serait bien si la fonction pouvait renvoyer les 10 000 premiers octets tout en laissant les 8 000 restants en attente pour de futures demandes de lecture plus petites, mais y en a-t-il des implémentations où cela se produirait? Où les 8 000 octets seraient-ils stockés en attendant ces futures demandes?size
plus de 1, eh bien ... Pour mémoire, il peut également y avoir des ioctls ou d'autres non-sens que vous pouvez appliquer au flux pour le rendre se comporter différemment, je n'ai pas approfondi cela.fread
travail tel que vous l'avez décrit sur de tels flux serait utile s'il y avait un moyen d'identifier les flux qui fonctionnent de cette manière.Je pense que c'est parce que C n'a pas de surcharge de fonctions. S'il y en avait, la taille serait redondante. Mais en C, vous ne pouvez pas déterminer la taille d'un élément de tableau, vous devez en spécifier une.
Considère ceci:
Si fwrite accepte le nombre d'octets, vous pouvez écrire ce qui suit:
Mais c'est tout simplement inefficace. Vous aurez sizeof (int) fois plus d'appels système.
Un autre point à prendre en compte est que vous ne voulez généralement pas qu'une partie d'un élément de tableau soit écrite dans un fichier. Vous voulez le nombre entier ou rien. fwrite renvoie un certain nombre d'éléments écrits avec succès. Donc, si vous découvrez que seuls 2 octets de poids faible d'un élément sont écrits, que feriez-vous?
Sur certains systèmes (en raison de l'alignement), vous ne pouvez pas accéder à un octet d'un entier sans créer une copie et un décalage.
la source