Domanda

che sto facendo un piccolo progetto in C, dopo un lungo periodo di tempo abbastanza lontano da esso. Questi capita di includere alcuni la gestione dei file. Ho notato che in vari documenti che ci sono funzioni che restituiscono maniglie FILE * e altri che ritornano (small integer) descrittori. Entrambe le serie di funzioni offrono gli stessi servizi di base di cui ho bisogno in modo che davvero non importa che uso.

Ma io sono curioso di sapere la saggezza collezione:? E 'meglio usare fopen() e amici, o open() e amici

Modifica Dal momento che qualcuno ha detto tamponata vs dispositivi senza buffer e di accesso, devo aggiungere che una parte di questo piccolo progetto sarà scrittura di un driver in userspace filesystem sotto FUSE. Così l'accesso a livello file potrebbe facilmente essere su un dispositivo (ad esempio un CD-ROM o un drive SCSI) come su un "file" (vale a dire l'immagine).

È stato utile?

Soluzione

L'obiezione che "fopen" è portatile e "aperto" è non è fasullo.

fopen fa parte della libc, aperta è una chiamata di sistema POSIX.

Ognuno di essi è più portabile come il luogo da cui provengono.

I / O per fopen'ed file è (è necessario assumere che sia, e per scopi pratici, è) tamponato da libc, descrittori di file aperto) 'ed (non sono tamponata da libc (possono anche essere, e di solito sono tamponata nel filesystem -. ma non tutto si apre () è un file su un filesystem

Qual è il punto di fopen'ing, per esempio, un nodo di dispositivo come / dev / sg0, per esempio, o / dev / tty0 ... Che cosa hai intenzione di fare? Si sta andando a fare un'ioctl su un file *? Buona fortuna.

Forse si vuole aprire con alcune bandiere come O_DIRECT - non ha senso con fopen ()

.

Altri suggerimenti

E 'meglio usare open () se si sta attaccando a sistemi Unix-like e come si potrebbe:

  • Avere un controllo più fine su unix bit dei permessi sulla creazione del file.
  • Utilizzare le funzioni di livello inferiore, come lettura / scrittura / mmap a differenza del C buffer flusso di funzioni di I / O.
  • descrittore di file Usa (fd) pianificazione basata IO (sondaggio, selezionare, ecc) Naturalmente, è possibile ottenere un fd da un file * utilizzando fileno (), ma bisogna fare attenzione a non mescolare FILE * funzioni di flusso basati con funzioni basate fd.
  • Aprire qualsiasi dispositivo speciale (non un file normale)

E 'meglio utilizzare fopen / fread / fwrite per la massima portabilità, in quanto questi sono funzioni standard C, le funzioni che ho citato sopra non sono.

opere fopen a un livello superiore a quello aperto .... fopen si restituisce un puntatore a file di flusso che è simile a l'astrazione flusso di leggere in C ++

ritorna aprirà un descrittore di file per il file aperto ... Non fornisce un'astrazione torrente e si è responsabile per la gestione dei bit e byte se stessi ... Questo è a un livello inferiore rispetto a fopen

stream stdio sono tamponati, mentre i descrittori di file aperti () non lo sono. Dipende da quello che vi serve. È inoltre possibile creare una dall'altra:

int fileno (FILE * stream) restituisce il descrittore di file per un file *, FILE * fdopen (int Fildes, const char * mode) crea un file * da un descrittore di file.

Fate attenzione quando mescolanza tamponata e non tamponata IO, dal momento che si perde ciò che è nel vostro buffer quando si Non dilavare con fflush ().

Sì. Quando avete bisogno di un manico di basso livello.

Su sistemi operativi UNIX, si può generalmente scambiare file handle e prese.

Inoltre, a basso livello maniglie fanno per una migliore compatibilità ABI di puntatori a file.

Di solito, si dovrebbe favorire utilizzando la libreria standard (fopen). Tuttavia, ci sono occasioni in cui sarà necessario utilizzare l'open direttamente.

Un esempio che mi viene in mente è quello di risolvere un bug in una versione precedente di Solaris che hanno reso fopen fallire dopo 256 file erano aperti. Questo è stato perché hanno usato erroniously un unsigned char per il campo fd nella loro attuazione struct FILE invece di un int. Ma questo era un caso molto specifico.

read () e write () usare senza buffer di I / O. ( fd : intero descrittore di file)

fread () e fwrite () uso buffer di I / O. ( FILE * puntatore struttura)

Dati binari scritti in un tubo con write () non possono in grado di leggere i dati binari con fread () , a causa di allineamenti di byte, dimensioni variabili, ecc E 'una merda-shoot.

La maggior parte di basso livello di codice di driver di periferica utilizza le chiamate di I / O senza buffer.

La maggior parte a livello di applicazione I / O utilizza tamponato.

L'uso delle file * e le sue funzioni associate è OK su base macchina per macchina: ma si perde la portabilità su altre architetture in lettura e scrittura di dati binari. fwrite () è tamponato I / O e può portare a risultati non attendibili se scritto per un architettura a 64 bit e corsa su un 32bit; o (Windows / Linux). La maggior parte sistemi operativi hanno macro di compatibilità all'interno del proprio codice per evitare questo.

Per I binari di basso livello portabilità / O read () e write () garanzia lo stesso binario di lettura e scrittura quando viene compilato su architetture diverse. La cosa fondamentale è quello di scegliere un modo o l'altro ed essere coerenti al riguardo, tutta la suite binario.

<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

Quindi, per l'uso di base io personalmente utilizzare quanto sopra senza mescolare linguaggi troppo.

Al contrario,

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

Questi forniscono un controllo granulare su lettura e la scrittura di byte (Consigliato per i dispositivi speciali e FIFO (tubi)).

Quindi, di nuovo, di utilizzare ciò che è necessario, ma mantenere coerenti nei vostri idiomi e interfacce. Se la maggior parte del codice di base utilizza una modalità, utilizzare anche questo, a meno che non ci sia un vero e proprio motivo per non. Entrambi i gruppi di I / O funzioni di libreria sono estremamente affidabili e utilizzato milioni di volte al giorno.

Nota - Se si sta interfacciando C di I / O con un altro linguaggio, (Perl, Python, Java, C #, Lua ...) Check out ciò che gli sviluppatori di queste lingue consigliamo prima di scrivere il codice C e risparmiare qualche problema.

fopen e le sue cugine sono tamponate. aperto, leggere e scrivere non tamponata. L'applicazione può o non può cura.

fprintf e scanf hanno un'API più ricca che permette di leggere e scrivere file di testo formattati. leggere e scrivere utilizzare le matrici fondamentali di byte. Conversioni e formattazioni devono essere fatti a mano.

La differenza tra descrittori di file e (FILE *) è davvero irrilevante.

Randy

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top