web-dev-qa-db-fra.com

C fopen vs ouvert

Y a-t-il une raison (autre que syntaxique) que vous voudriez utiliser

FILE *fdopen(int fd, const char *mode);

ou

FILE *fopen(const char *path, const char *mode);

au lieu de

int open(const char *pathname, int flags, mode_t mode);

lors de l'utilisation de C dans un environnement Linux?

196
LJM

Premièrement, il n'y a pas de bonne raison d'utiliser fdopen si fopen est une option et open est l'autre choix possible. Vous n'auriez pas dû utiliser open pour ouvrir le fichier si vous voulez un _FILE *_. Donc, inclure fdopen dans cette liste est incorrect et déroutant car il ne ressemble pas beaucoup aux autres. Je vais maintenant passer à l’ignorer, car la distinction importante est ici entre un C standard _FILE *_ et un descripteur de fichier spécifique au système d’exploitation.

Il existe quatre raisons principales d'utiliser fopen au lieu de open.

  1. fopen vous fournit un tampon IO qui peut s'avérer beaucoup plus rapide que ce que vous faites avec open.
  2. fopen effectue la traduction de fin de ligne si le fichier n'est pas ouvert en mode binaire, ce qui peut s'avérer très utile si votre programme est jamais porté dans un environnement non Unix.
  3. Un _FILE *_ vous donne la possibilité d'utiliser fscanf et d'autres fonctions stdio.
  4. Votre code devra peut-être un jour être porté sur une autre plate-forme prenant uniquement en charge le ANSI C et non la fonction open.

À mon avis, la fin de ligne se trouve plus souvent dans votre chemin qu’elle ne vous aide, et l’analyse de fscanf est si faible que vous finissez inévitablement par la lancer en faveur de quelque chose de plus utile.

Et la plupart des plates-formes prenant en charge C ont une fonction open.

Cela laisse la question tampon. Dans les endroits où vous lisez ou écrivez principalement un fichier de manière séquentielle, la prise en charge de la mise en mémoire tampon est vraiment utile et représente une grande amélioration de la vitesse. Mais cela peut entraîner des problèmes intéressants, dans lesquels les données ne se retrouvent pas dans le fichier alors que vous vous attendez à ce qu'elles soient là. Vous devez vous rappeler de fclose ou fflush aux moments appropriés.

Si vous effectuez des recherches (alias fsetpos ou fseek dont la seconde est légèrement plus délicate à utiliser de manière conforme aux normes), l'utilité de la mise en mémoire tampon diminue rapidement.

Bien sûr, mon parti pris est que j’ai tendance à travailler beaucoup avec des sockets, et le fait que vous vouliez vraiment faire du non-blocage IO (que _FILE *_ échoue totalement à supporter de manière raisonnable) sans aucun tampon et souvent avec des exigences d’analyses complexes colorent vraiment mes perceptions.

226
Omnifarious

open() est un appel OS de bas niveau. fdopen() convertit un descripteur de fichier de niveau os en abstraction FILE de niveau supérieur du langage C. fopen() appelle open() en arrière-plan et vous attribue directement un pointeur FILE.

L’utilisation d’objets FILE plutôt que de descripteurs de fichiers bruts présente plusieurs avantages, ce qui inclut une plus grande facilité d’utilisation mais également d’autres avantages techniques, tels que la mise en mémoire tampon intégrée. En particulier, la mise en mémoire tampon procure généralement un avantage considérable en termes de performances.

48
Emil H

fopen vs ouvert en C

1) fopen est un fonction de bibliothèque alors que open est un appel système.

2) fopen fournit IO en mémoire tampon, ce qui est plus rapide comparé à open qui est sans mémoire tampon.

3) fopen est portable alors que open pas portable (ouvert est spécifique à l'environnement).

4) fopen renvoie un pointeur sur une structure FILE (FILE *); open renvoie un entier identifiant le fichier.

5) Un FILE * vous donne la possibilité d'utiliser fscanf et d'autres fonctions stdio.

27
Yogeesh H T

Si vous avez un FILE *, vous pouvez utiliser des fonctions telles que fscanf, fprintf et fgets etc. Si vous avez juste le descripteur de fichier, vous avez limité (mais probablement plus rapide) routines d'entrée et de sortie read, write etc.

11
dreamlax

À moins que vous ne fassiez partie des 0,1% d'applications où open présente des avantages réels en termes de performances, il n'y a vraiment aucune bonne raison de ne pas utiliser fopen. En ce qui concerne fdopen, si vous ne jouez pas avec les descripteurs de fichier, vous n'avez pas besoin de cet appel.

Tenez-vous-en à fopen et à sa famille de méthodes (fwrite, fread, fprintf, etc.) et vous serez très satisfait. De manière tout aussi importante, les autres programmeurs seront satisfaits de votre code.

11
user7116

Utiliser open, read, write signifie que vous devez vous soucier des interaptions des signaux.

Si l'appel a été interrompu par un gestionnaire de signal, les fonctions renverront -1 et définiront errno sur EINTR.

Donc, la bonne façon de fermer un fichier serait

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
7
digy

open () sera appelé à la fin de chacune des fonctions de la famille fopen (). open () est un appel système et fopen () sont fournis par les bibliothèques en tant que fonctions d'encapsulation faciles à utiliser pour l'utilisateur

4
theadnangondal

open() est un appel système spécifique aux systèmes Unix. Il renvoie un descripteur de fichier. Vous pouvez écrire dans un descripteur de fichier en utilisant write(), qui est un autre appel système.
fopen() est un appel de fonction ANSI C qui renvoie un pointeur de fichier et qui est portable pour les autres systèmes d'exploitation. Nous pouvons écrire dans un pointeur de fichier en utilisant fprintf.

Sous Unix:
Vous pouvez obtenir un pointeur de fichier à partir du descripteur de fichier en utilisant:

fP = fdopen(fD, "a");

Vous pouvez obtenir un descripteur de fichier à partir du pointeur de fichier en utilisant:

fD = fileno (fP);
4
Arun Chettoor

Dépend également de ce que les drapeaux doivent être ouverts. En ce qui concerne l'utilisation pour l'écriture et la lecture (et la portabilité), f * doit être utilisé, comme indiqué ci-dessus.

Toutefois, si vous souhaitez spécifier plus que des indicateurs standard (comme les indicateurs rw et append), vous devez utiliser une API spécifique à la plate-forme (telle que POSIX open) ou une bibliothèque qui résume ces informations. La norme C n'a pas de tels drapeaux.

Par exemple, vous voudrez peut-être ouvrir un fichier, s'il existe déjà. Si vous ne spécifiez pas l'indicateur de création, le fichier doit exister. Si vous ajoutez exclusif à créer, le fichier ne sera créé que s'il n'existe pas. Il y en a beaucoup plus.

Par exemple, sur les systèmes Linux, il existe une interface LED exposée via sysfs. Il expose la luminosité de la led à travers un fichier. Écrire ou lire un nombre sous forme de chaîne allant de 0 à 255. Bien sûr, vous ne voulez pas créer ce fichier et y écrire uniquement s’il existe. La bonne chose maintenant: utilisez fdopen pour lire/écrire ce fichier en utilisant les appels standard.

2
Ritualmaster

J'ai remplacé open () par fopen () pour mon application, car fopen provoquait des lectures doubles à chaque fois que j'exécutais fopen fgetc. Les doubles lectures ont perturbé ce que j'essayais d'accomplir. open () semble juste faire ce que vous lui demandez.

1
Ersatz Splatt