Question

Je fais un petit projet en C après une longue période d'absence.Ceux-ci incluent une certaine gestion de fichiers.J'ai remarqué dans diverses documentations qu'il existe des fonctions qui renvoient FILE * handles et autres qui renvoient des descripteurs (petits entiers).Les deux ensembles de fonctions offrent les mêmes services de base dont j’ai besoin, donc peu importe que j’utilise.

Mais je suis curieux de connaître la sagesse de la collection :est-il préférable d'utiliser fopen() et amis, ou open() et amis?

Modifier Puisque quelqu'un a mentionné les périphériques tamponnés ou non tamponnés et l'accès, je dois ajouter qu'une partie de ce petit projet consistera à écrire un pilote de système de fichiers en espace utilisateur sous FUSE.Ainsi, l'accès au niveau des fichiers pourrait tout aussi bien se faire sur un appareil (par ex.un CDROM ou un lecteur SCSI) comme sur un "fichier" (c'est-à-direune image).

Était-ce utile?

La solution

L'objection selon laquelle "fopen" est portable et "ouvert" n'est pas est faux.

fopen fait partie de libc, ouvert est un appel système POSIX.

Chacun d'eux est aussi portable que l'endroit où ils viennent.

i / o à fopen'ed fichiers est (vous devez supposer qu'il peut être, et pour des raisons pratiques, il est) amorti par libc, descripteurs de fichiers () 'ed ne sont pas stockées par libc (ils peuvent bien être, et généralement sont mises en tampon dans le système de fichiers -. mais pas tout ce que vous ouvrez () est un fichier sur un système de fichiers

Quel est le point de fopen'ing, par exemple, un nœud de périphérique / dev / sg0, par exemple, ou / dev / tty0 ... Qu'est-ce que tu vas faire? Vous allez faire un ioctl sur un FILE *? Bonne chance.

Peut-être que vous voulez ouvrir avec des drapeaux comme O_DIRECT - n'a pas de sens avec fopen ()

.

Autres conseils

Il est préférable d'utiliser open () si vous en tenir à des systèmes Unix et vous pourriez aimer:

  • Avoir un contrôle plus fin sur les bits d'autorisation unix sur la création de fichiers.
  • Utilisez les fonctions de bas niveau, tels que lecture / écriture / mmap par opposition aux fonctions C flux mis en mémoire tampon E / S.
  • descripteur de fichier Utilisation (fd) sur la base de planification IO (sondage, sélectionnez, etc.) Vous pouvez bien sûr obtenir un fd d'un fichier * en utilisant fileno (), mais il faut veiller à ne pas mélanger les fonctions de flux à base de fichiers * avec fd fonctions basées.
  • Ouvrez un dispositif spécial (pas un fichier régulier)

Il est préférable d'utiliser fopen / fread / fwrite pour une portabilité maximale, car ceux-ci sont des fonctions standard C, les fonctions que je l'ai mentionné ci-dessus ne sont pas.

œuvres fopen à un niveau supérieur ouvert .... fopen vous renvoie un pointeur sur FILE flux qui est similaire à l'abstraction de flux que vous lisez en C ++

open retourne vous un descripteur de fichier pour le fichier ouvert ... Il ne vous fournit pas une abstraction de flux et vous êtes responsable de la gestion des bits et octets vous-même ... C'est à un niveau inférieur par rapport à fopen

flux STDIO sont tamponnées, alors que les descripteurs de fichiers () ne sont pas. Dépend de ce dont vous avez besoin. Vous pouvez également créer un de l'autre:

int fileno (FILE * stream) renvoie le descripteur de fichier pour un FILE *, FILE * fdopen (int fd, le mode const char *) crée un fichier * à partir d'un descripteur de fichier.

Soyez prudent lorsque vous entremêlement tamponnés et non tamponnés IO, puisque vous perdrez ce qui est dans votre mémoire tampon lorsque vous ne vident pas avec fflush ().

Oui. Lorsque vous avez besoin d'une poignée de bas niveau.

Sur les systèmes d'exploitation UNIX, vous pouvez échanger en général poignées de fichiers et prises.

En outre, les poignées de bas niveau pour faire une meilleure compatibilité ABI que les pointeurs de fichiers.

En général, vous devriez favoriser l'utilisation de la bibliothèque standard (fopen). Cependant, il y a des occasions où vous aurez besoin d'utiliser directement ouvert.

Un exemple qui vient à l'esprit est de travailler autour d'un bogue dans une ancienne version de solaris qui ont fait échouer après fopen 256 dossiers ont été ouverts. En effet, ils ont utilisé un erroniously unsigned char pour le champ fd dans leur mise en œuvre struct FILE au lieu d'un int. Mais ce fut un cas très spécifique.

lire() & écrire() utilisez des E/S sans tampon.(fd:descripteur de fichier entier)

fread() & fécrire() utilisez des E/S tamponnées.(DÉPOSER* pointeur de structure)

Données binaires écrites dans un tube avec écrire() Peut-être pas être capable de lire des données binaires avec fread(), en raison des alignements d'octets, des tailles variables, etc.C'est une connerie.

La plupart des codes de pilotes de périphériques de bas niveau utilisent des appels d'E/S sans tampon.

La plupart des E/S au niveau de l'application utilisent une mémoire tampon.

Utilisation du DÉPOSER* Et ses fonctions associées sont ok sur une base de machine par machine:Mais la portabilité est perdue dans d'autres architectures dans la lecture et l'écriture de données binaires.FWrite () est des E / S tamponnées et peut conduire à des résultats peu fiables s'ils sont écrits pour une architecture 64 bits et exécuter sur un 32 bits;ou (Windows/Linux).La plupart des systèmes d'exploitation ont des macros de compatibilité dans leur propre code pour éviter cela.

Pour la portabilité des E/S binaires de bas niveau lire() et écrire() garantie Le même binaire lit et écrit lorsqu’il est compilé sur des architectures différentes.L’essentiel est de choisir une façon ou une autre et d’être cohérent à ce sujet. dans l’ensemble de la suite binaire.

<stdio.h>  // mostly FILE*  some fd input/output parameters for compatibility
             // gives you a lot of helper functions -->
List of Functions
       Function      Description
       ───────────────────────────────────────────────────────────────────
       clearerr      check and reset stream status
       fclose        close a stream
       fdopen        stream open functions //( fd argument, returns FILE*)                      feof          check and reset stream status
       ferror        check and reset stream status
       fflush        flush a stream
       fgetc         get next character or word from input stream
       fgetpos       reposition a stream
       fgets         get a line from a stream
       fileno        get file descriptor   // (FILE* argument, returns fd) 
       fopen         stream open functions
       fprintf       formatted output conversion
       fpurge        flush a stream
       fputc         output a character or word to a stream
       fputs         output a line to a stream
       fread         binary stream input/output
       freopen       stream open functions
       fscanf        input format conversion
       fseek         reposition a stream
       fsetpos       reposition a stream
       ftell         reposition a stream
       fwrite        binary stream input/output
       getc          get next character or word from input stream
       getchar       get next character or word from input stream
       gets          get a line from a stream
       getw          get next character or word from input stream
       mktemp        make temporary filename (unique)
       perror        system error messages
       printf        formatted output conversion
       putc          output a character or word to a stream
       putchar       output a character or word to a stream
       puts          output a line to a stream
       putw          output a character or word to a stream
       remove        remove directory entry
       rewind        reposition a stream
       scanf         input format conversion
       setbuf        stream buffering operations
       setbuffer     stream buffering operations
       setlinebuf    stream buffering operations
       setvbuf       stream buffering operations
       sprintf       formatted output conversion
       sscanf        input format conversion
       strerror      system error messages
       sys_errlist   system error messages
       sys_nerr      system error messages
       tempnam       temporary file routines
       tmpfile       temporary file routines
       tmpnam        temporary file routines
       ungetc        un-get character from input stream
       vfprintf      formatted output conversion
       vfscanf       input format conversion
       vprintf       formatted output conversion
       vscanf        input format conversion
       vsprintf      formatted output conversion
       vsscanf       input format conversion

Donc, pour une utilisation de base, j'utiliserais personnellement ce qui précède sans trop mélanger les idiomes.

Par contre,

<unistd.h>   write()
             lseek()
             close()
             pipe()
<sys/types.h>
<sys/stat.h>
<fcntl.h>  open()
           creat()
           fcntl() 
all use file descriptors.

Ceux-ci fournissent un contrôle précis sur la lecture et l’écriture des octets (recommandé pour les appareils spéciaux et les FIFO (tuyaux) ).

Encore une fois, utilisez ce dont vous avez besoin, mais restez cohérent dans vos idiomes et vos interfaces.Si la majeure partie de votre base de code utilise un mode, utilisez-le aussi, à moins qu’il n’y en ait une vraie raison de ne pas le faire.Les deux ensembles de fonctions de la bibliothèque d’E/S sont extrêmement fiables et utilisé des millions de fois par jour.

note-- Si vous interfaces des E/S C avec un autre langage, (Perl, Python, Java, C#, Lua...) vérifier ce que les développeurs de ces langages recommander avant d’écrire votre code C et vous épargner des ennuis.

fopen et ses cousines sont mises en mémoire tampon. ouvrir, lire et écrire ne sont pas en mémoire tampon. Votre application peut ou ne peut pas prendre soin.

fprintf et scanf ont une API plus riche qui vous permet de lire et d'écrire des fichiers texte au format. lire et écrire utiliser des tableaux d'octets fondamentaux. Les conversions et la mise en forme doivent être fabriqués à la main.

La différence entre les descripteurs de fichiers et (FILE *) est vraiment sans conséquence.

Randy

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top