Quelle est la différence entre un descripteur de fichier et un pointeur de fichier?

Réponses:

144

Un descripteur de fichier est un "handle" d'entier de bas niveau utilisé pour identifier un fichier ouvert (ou socket, ou autre) au niveau du noyau, sous Linux et d'autres systèmes de type Unix.

Vous passez des descripteurs de fichiers "nus" aux appels Unix réels, tels que read(), write()etc.

Un FILEpointeur est une construction de niveau bibliothèque standard C, utilisée pour représenter un fichier. L' FILEencapsule le descripteur de fichier et ajoute une mise en mémoire tampon et d'autres fonctionnalités pour faciliter les E / S.

Vous passez des FILEpointeurs vers des fonctions C standard telles que fread()et fwrite().

se détendre
la source
@nvl: fildes est sûrement disponible pour Windows, par exemple msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm
2
@unwind Que voulez-vous dire par descripteurs de fichiers "nus"? La référence liée indique que le fdest le premier argument de read(). Pourquoi appelez-vous cela nu?
Geek
3
@Geek Comparé au type de bibliothèque standard FILE *, le descripteur de fichier entier est "less wrapped", c'est-à-dire "nu".
détendre le
57

L'un est tamponné ( FILE *) et l'autre non. En pratique, vous voulez l'utiliser FILE *presque toujours lorsque vous lisez à partir d'un 'vrai' fichier (c'est-à-dire sur le lecteur), à moins que vous ne sachiez ce que vous faites ou à moins que votre fichier ne soit en fait une socket ou quelque chose de similaire.

Vous pouvez obtenir le descripteur de fichier à l' FILE *aide de fileno()et vous pouvez ouvrir une mémoire tampon à FILE *partir d'un descripteur de fichier en utilisantfdopen()

Ben
la source
12
+1 pour signaler fileno (), l'organisation des pages de manuel rend celle-ci difficile à trouver. Idem pour fdopen ().
BD à Rivenhill le
20

Un descripteur de fichier est juste un entier que vous obtenez de l' open()appel POSIX . En utilisant le standard C, fopen()vous récupérez une FILEstructure. La FILEstructure contient ce descripteur de fichier entre autres, comme l'indicateur de fin de fichier et d'erreur, la position du flux, etc.

Donc, utiliser fopen()vous donne une certaine quantité d'abstraction par rapport à open(). En général, vous devriez l'utiliser fopen()car c'est plus portable et vous pouvez utiliser toutes les autres fonctions C standard qui utilisent la FILEstructure, ie, fprintf()et la famille.

Il n'y a aucun problème de performances avec l'un ou l'autre.

Martin Wickman
la source
8
+1 pour la portabilité. FILE fait partie de la bibliothèque standard C (retour à C89 / C90); les descripteurs de fichiers ne le sont pas.
tomlogic
15

Descripteur de fichier vs pointeur de fichier

Descripteur de fichier:

Le descripteur de fichier est une valeur entière renvoyée par open()un appel système.

int fd = open (filePath, mode);

  1. Gestionnaire de niveau bas / noyau.
  2. passe à read () et write () des appels système UNIX.
  3. N'inclut pas la mise en mémoire tampon et de telles fonctionnalités.
  4. Moins portable et manque d'efficacité.

Pointeur de fichier:

Le pointeur de fichier est un pointeur vers une structure C renvoyée par la fopen()fonction de bibliothèque, qui est utilisée pour identifier un fichier, encapsuler le descripteur de fichier, la fonctionnalité de mise en mémoire tampon et toutes les autres fonctionnalités nécessaires aux opérations d'E / S. Le pointeur de fichier est de type FILE , dont la définition se trouve dans "/usr/include/stdio.h" . Cette définition peut varier d'un compilateur à l'autre.

FILE *fp = fopen (filePath, mode);

// A FILE Structure returned by fopen 
    typedef struct 
    {
        unsigned char   *_ptr;
        int     _cnt;
        unsigned char   *_base;
        unsigned char   *_bufendp;
        short   _flag;
        short   _file;
        int     __stdioid;
        char    *__newbase;
#ifdef _THREAD_SAFE
        void *_lock;
#else
        long    _unused[1];
#endif
#ifdef __64BIT__
        long    _unused1[4];
#endif /* __64BIT__ */
    } FILE;
  1. C'est une interface de haut niveau.
  2. Passé aux fonctions fread () et fwrite ().
  3. Comprend la mise en mémoire tampon, l'indication d'erreur et la détection EOF, etc.
  4. Fournit une portabilité et une efficacité accrues.
Yogeesh HT
la source
1
Êtes-vous en mesure de soutenir cette affirmation d'efficacité accrue? Je n'ai jamais entendu ça.
Gid
1
L'allégation d '«efficacité» pourrait être due à la mise en mémoire tampon. Avec un descripteur de fichier, chaque read () ou write () est un appel système, et chaque appel système doit être considéré comme coûteux. Avec un FILE *, la mise en mémoire tampon signifie que certaines lectures et écritures ne seront pas des appels système.
Mike Spear
12

Vous voulez ajouter des points qui pourraient être utiles.

À PROPOS FILE *

  1. ne peut pas être utilisé pour la communication interprocessus (IPC).
  2. utilisez-le lorsque vous avez besoin d'E / S tamponnées à des fins générales (printf, frpintf, snprintf, scanf)
  3. Je l'utilise plusieurs fois pour les journaux de débogage. exemple,

                 FILE *fp;
                 fp = fopen("debug.txt","a");
                 fprintf(fp,"I have reached till this point");
                 fclose(fp);
    

À PROPOS FILE DESCRIPTOR

  1. Il est généralement utilisé pour IPC.

  2. Donne un contrôle de bas niveau aux fichiers sur les systèmes * nix (périphériques, fichiers, sockets, etc.), donc plus puissant que le FILE *.

Akshay Patil
la source
Ne pouvez-vous pas utiliser fdopen()pour faire des choses comme IPC et des appareils avec FILE*?
osvein
En fait, oui et non. Vous ne pouvez pas configurer et initialiser IPC avec FILE*, mais vous pouvez créer un à FILE*partir d'un descripteur de fichier ( fdopen()) et fermer ultérieurement le FILEfermera également le descripteur. Par conséquent, vous pouvez faire IPC, mais vous devez gérer un peu les descripteurs de fichiers pour faciliter tout IPC direct.
Micah W
3

FILE *est plus utile lorsque vous travaillez avec des fichiers texte et entrée / sortie utilisateur, car il vous permet d'utiliser les fonctions de l' API comme sprintf(), sscanf(), fgets(), feof()etc.

L'API de descripteur de fichier est de bas niveau, elle permet donc de travailler avec des sockets, des tubes, des fichiers mappés en mémoire (et des fichiers normaux, bien sûr).

qrdl
la source
1
+1 parce que vous avez ajouté des fichiers mappés en mémoire, car à partir de ma lecture actuelle, les autres réponses ont déjà été fournies.
ernie.cordell
3

Juste un petit mot pour terminer la discussion (si intéressé) ...

fopenpeut être non sécurisé, et vous devriez probablement utiliser fopen_sou openavec un jeu de bits exclusif. C1X offre des xmodes, vous pouvez donc fopenavec les modes "rx", "wx"etc.

Si vous utilisez open, vous pourriez envisager open(..., O_EXCL | O_RDONLY,... )ou open(..., O_CREAT | O_EXCL | O_WRONLY,... ).

Voir, par exemple, Ne pas faire d'hypothèses sur fopen () et la création de fichiers .

jww
la source
Comme fopen_sne semble pas être disponible avec POSIX, je suppose que la soultion la plus portable serait de open(2)et ensuite fdopen(2). (laissant les fenêtres de côté). De plus, qu'est-ce qui serait plus rapide fopen_s()ou open(2)suivi fdopen(2)?
Mihir
1

Les appels système utilisent principalement un descripteur de fichier, par exemple readet write. La fonction de bibliothèque utilisera les pointeurs de fichier ( printf, scanf). Mais les fonctions de bibliothèque utilisent uniquement des appels système en interne.

Pavunkumar
la source
Je ne sais pas pourquoi vous dites que les fonctions de bibliothèque n'utilisent que des appels système internes: si vous parlez des fonctions CI / O standard (ou toute autre fonction d'ailleurs), je ne suis pas sûr que ce soit (universellement?) Vrai. Sinon, ce n'est pas ce que vous avez dit, alors j'aimerais que le langage de votre message soit un peu nettoyé. La dernière phrase me déroute.
ernie.cordell
1

J'ai trouvé une bonne ressource ici , donnant un aperçu de haut niveau des différences entre les deux:

Lorsque vous souhaitez effectuer une entrée ou une sortie dans un fichier, vous avez le choix entre deux mécanismes de base pour représenter la connexion entre votre programme et le fichier: les descripteurs de fichier et les flux. Les descripteurs de fichiers sont représentés comme des objets de type int, tandis que les flux sont représentés comme des objets FILE *.

Les descripteurs de fichier fournissent une interface primitive de bas niveau pour les opérations d'entrée et de sortie. Les descripteurs de fichiers et les flux peuvent représenter une connexion à un périphérique (tel qu'un terminal), ou un tube ou une socket pour communiquer avec un autre processus, ainsi qu'un fichier normal. Mais, si vous souhaitez effectuer des opérations de contrôle spécifiques à un type particulier de périphérique, vous devez utiliser un descripteur de fichier; il n'y a aucune possibilité d'utiliser les flux de cette manière. Vous devez également utiliser des descripteurs de fichier si votre programme doit effectuer une entrée ou une sortie dans des modes spéciaux, tels que l'entrée non bloquante (ou interrogée) (voir Indicateurs d'état de fichier).

Les flux fournissent une interface de niveau supérieur, superposée aux fonctionnalités de descripteur de fichier primitif. L'interface de flux traite tous les types de fichiers à peu près de la même manière, la seule exception étant les trois styles de mise en mémoire tampon que vous pouvez choisir (voir Mise en mémoire tampon de flux).

Le principal avantage de l'utilisation de l'interface de flux est que l'ensemble des fonctions permettant d'effectuer des opérations d'entrée et de sortie réelles (par opposition aux opérations de contrôle) sur les flux est beaucoup plus riche et plus puissant que les fonctionnalités correspondantes pour les descripteurs de fichiers. L'interface de descripteur de fichier ne fournit que des fonctions simples pour transférer des blocs de caractères, mais l'interface de flux fournit également de puissantes fonctions d'entrée et de sortie formatées (printf et scanf) ainsi que des fonctions d'entrée et de sortie orientées caractères et lignes.

Étant donné que les flux sont implémentés en termes de descripteurs de fichier, vous pouvez extraire le descripteur de fichier d'un flux et effectuer des opérations de bas niveau directement sur le descripteur de fichier. Vous pouvez également ouvrir initialement une connexion en tant que descripteur de fichier, puis créer un flux associé à ce descripteur de fichier.

En général, vous devriez vous en tenir à l'utilisation de flux plutôt que de descripteurs de fichiers, sauf si vous souhaitez effectuer une opération spécifique qui ne peut être effectuée que sur un descripteur de fichier. Si vous êtes un programmeur débutant et que vous n'êtes pas sûr des fonctions à utiliser, nous vous suggérons de vous concentrer sur les fonctions d'entrée formatées (voir Entrée formatée) et les fonctions de sortie formatées (voir Sortie formatée).

Si vous êtes préoccupé par la portabilité de vos programmes vers des systèmes autres que GNU, vous devez également savoir que les descripteurs de fichiers ne sont pas aussi portables que les flux. Vous pouvez vous attendre à ce que tout système exécutant ISO C prenne en charge les flux, mais les systèmes non GNU peuvent ne pas du tout prendre en charge les descripteurs de fichiers, ou peuvent implémenter uniquement un sous-ensemble des fonctions GNU qui fonctionnent sur des descripteurs de fichiers. Cependant, la plupart des fonctions de descripteur de fichier de la bibliothèque GNU C sont incluses dans le standard POSIX.1.

Suraj Jain
la source