Risposte:
Un descrittore di file è un "handle" intero di basso livello utilizzato per identificare un file aperto (o socket, o qualsiasi altra cosa) a livello di kernel, in Linux e altri sistemi Unix-like.
Si passano descrittori di file "nudi" alle effettive chiamate Unix, come read(), write()e così via.
Un FILEpuntatore è un costrutto a livello di libreria standard C, utilizzato per rappresentare un file. Il FILEwrapping del descrittore di file e aggiunge buffering e altre funzionalità per rendere più facile l'I / O.
Si passano i FILEpuntatori a funzioni C standard come fread()e fwrite().
fdè il primo argomento per read(). Perché lo chiami nudo?
FILE *tipo della libreria standard , il descrittore di file intero è "meno impacchettato", cioè "nudo".
Uno è bufferizzato ( FILE *) e l'altro no. In pratica, vuoi usare FILE *quasi sempre quando stai leggendo da un file 'reale' (cioè sul disco), a meno che tu non sappia cosa stai facendo oa meno che il tuo file non sia effettivamente un socket o giù di lì ..
Puoi ottenere il descrittore di file da FILE *using fileno()e puoi aprire un buffer FILE *da un descrittore di file usandofdopen()
Un descrittore di file è solo un numero intero che ottieni dalla open()chiamata POSIX . Usando lo standard C fopen()ottieni FILEindietro una struttura. La FILEstruttura contiene questo descrittore di file tra le altre cose come la fine del file e l'indicatore di errore, la posizione del flusso ecc.
Quindi l'utilizzo fopen()ti dà una certa quantità di astrazione rispetto a open(). In generale dovresti usarlo fopen()poiché è più portabile e puoi usare tutte le altre funzioni C standard che usano la FILEstruttura, cioè, fprintf()e la famiglia.
Non ci sono problemi di prestazioni nell'utilizzo di entrambi.
Descrittore di file vs puntatore di file
Descrittore di file:
File Descriptor è un valore intero restituito dalla open()chiamata di sistema.
int fd = open (filePath, mode);
Puntatore file:
File Pointer è un puntatore a una struttura C restituita dalla fopen()funzione di libreria, che viene utilizzata per identificare un file, avvolgere il descrittore di file, funzionalità di buffering e tutte le altre funzionalità necessarie per le operazioni di I / O. Il puntatore di file è di tipo FILE , la cui definizione può essere trovato in "/usr/include/stdio.h" . Questa definizione può variare da un compilatore all'altro.
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;
Vuoi aggiungere punti che potrebbero essere utili.
DI FILE *
Lo uso molte volte per i log di debug. esempio,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);DI FILE DESCRIPTOR
Viene generalmente utilizzato per IPC.
Fornisce un controllo di basso livello ai file sui sistemi * nix (dispositivi, file, socket, ecc.), Quindi più potente del FILE *.
fdopen()per fare cose come IPC e dispositivi con FILE*?
FILE*, ma è possibile creare un FILE*da un descrittore di file ( fdopen()) e la successiva chiusura di FILEchiuderà anche il descrittore. Pertanto, puoi eseguire IPC, ma devi occuparti un po 'dei descrittori di file per facilitare qualsiasi IPC diretto.
FILE *è più utile quando si lavora con i file di testo e user input / output, perché consente di utilizzare le funzioni API come sprintf(), sscanf(), fgets(), feof()etc.
L'API del descrittore di file è di basso livello, quindi consente di lavorare con socket, pipe, file mappati in memoria (e file normali, ovviamente).
Solo una nota per concludere la discussione (se interessati) ....
fopenpuò essere insicuro e probabilmente dovresti usare fopen_so opencon set di bit esclusivi. C1X sta offrendo xmodalità, in modo da poter fopencon i modi "rx", "wx"e così via
Se usi open, potresti considerare open(..., O_EXCL | O_RDONLY,... )o open(..., O_CREAT | O_EXCL | O_WRONLY,... ).
Vedere, ad esempio, Non fare supposizioni su fopen () e sulla creazione di file .
fopen_sche non sembra essere disponibile con POSIX, presumo che l'anima più portatile sarebbe quella di open(2)e poi fdopen(2). (lasciando da parte le finestre). Inoltre, cosa sarebbe più veloce fopen_s()o open(2)seguito da fdopen(2)?
Le chiamate di sistema utilizzano principalmente descrittori di file, ad esempio reade write. La funzione di libreria utilizzerà i puntatori di file ( printf, scanf). Tuttavia, le funzioni di libreria utilizzano solo chiamate di sistema interne.
Ho trovato una buona risorsa qui , fornendo una panoramica di alto livello delle differenze tra i due:
Quando si desidera eseguire l'input o l'output in un file, è possibile scegliere tra due meccanismi di base per rappresentare la connessione tra il programma e il file: descrittori di file e flussi. I descrittori di file sono rappresentati come oggetti di tipo int, mentre i flussi sono rappresentati come oggetti FILE *.
I descrittori di file forniscono un'interfaccia primitiva di basso livello per le operazioni di input e output. Sia i descrittori di file che i flussi possono rappresentare una connessione a un dispositivo (come un terminale) o una pipe o un socket per la comunicazione con un altro processo, nonché un file normale. Tuttavia, se si desidera eseguire operazioni di controllo specifiche per un particolare tipo di dispositivo, è necessario utilizzare un descrittore di file; non ci sono strutture per utilizzare i flussi in questo modo. È inoltre necessario utilizzare i descrittori di file se il programma deve eseguire l'input o l'output in modalità speciali, come l'input non bloccante (o con polling) (vedere Flag di stato del file).
I flussi forniscono un'interfaccia di livello superiore, sovrapposta alle funzionalità primitive del descrittore di file. L'interfaccia stream tratta tutti i tipi di file praticamente allo stesso modo, l'unica eccezione sono i tre stili di buffering che puoi scegliere (vedi Stream Buffering).
Il vantaggio principale dell'utilizzo dell'interfaccia stream è che l'insieme di funzioni per eseguire effettive operazioni di input e output (al contrario delle operazioni di controllo) sui flussi è molto più ricco e potente delle corrispondenti funzionalità per i descrittori di file. L'interfaccia del descrittore di file fornisce solo semplici funzioni per il trasferimento di blocchi di caratteri, ma l'interfaccia stream fornisce anche potenti funzioni di input e output formattati (printf e scanf), nonché funzioni per input e output orientati ai caratteri e alla riga.
Poiché i flussi sono implementati in termini di descrittori di file, è possibile estrarre il descrittore di file da un flusso ed eseguire operazioni di basso livello direttamente sul descrittore di file. È inoltre possibile aprire inizialmente una connessione come descrittore di file e quindi creare un flusso associato a tale descrittore di file.
In generale, dovresti continuare a usare flussi piuttosto che descrittori di file, a meno che non ci sia qualche operazione specifica che desideri fare che può essere eseguita solo su un descrittore di file. Se sei un programmatore principiante e non sei sicuro di quali funzioni utilizzare, ti suggeriamo di concentrarti sulle funzioni di input formattato (vedi Input formattato) e sulle funzioni di output formattato (vedi Output formattato).
Se sei preoccupato per la portabilità dei tuoi programmi su sistemi diversi da GNU, dovresti anche essere consapevole che i descrittori di file non sono portabili come gli stream. Ci si può aspettare che qualsiasi sistema che esegue ISO C supporti i flussi, ma i sistemi non GNU potrebbero non supportare affatto i descrittori di file, o potrebbero implementare solo un sottoinsieme delle funzioni GNU che operano sui descrittori di file. Tuttavia, la maggior parte delle funzioni del descrittore di file nella libreria GNU C sono incluse nello standard POSIX.1.