C fopen vs open


219

C'è qualche motivo (oltre a quelli sintattici) che vorresti usare

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

o

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

invece di

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

quando si utilizza C in un ambiente Linux?


Intendevi fdopene openo fopene open?
user7116,

Non vuoi dire fopen, non fdopen?
Onnipotente il

9
fopenfa parte della libreria C standard, opennon lo è. Utilizzare fopenquando si scrive codice portatile.
Aziz,

Sì, intendevo fopen. L'ho appena aggiornato, ma penso che si applichi lo stesso principio.
LJM,

6
@Aziz, però openè una funzione POSIX.
dreamlax,

Risposte:


242

Innanzitutto, non esiste un motivo particolarmente valido per utilizzare fdopense fopenè un'opzione ed openè l'altra scelta possibile. Non avresti dovuto usare openper aprire il file in primo luogo se vuoi un FILE *. Quindi includere fdopenin quell'elenco è errato e confuso perché non è molto simile agli altri. Ora procederò a ignorarlo perché la distinzione importante qui è tra uno standard C FILE *e un descrittore di file specifico del sistema operativo.

Esistono quattro motivi principali da utilizzare fopenanziché open.

  1. fopenti fornisce buffering IO che potrebbe rivelarsi molto più veloce di quello che stai facendo open.
  2. fopen esegue la traduzione di fine riga se il file non viene aperto in modalità binaria, il che può essere molto utile se il tuo programma viene mai portato su un ambiente non Unix (anche se il mondo sembra convergere solo su LF (eccetto le reti basate su testo IETF protocolli come SMTP e HTTP e simili)).
  3. A FILE *ti dà la possibilità di usare fscanfe altre funzioni stdio.
  4. Un giorno il tuo codice potrebbe dover essere trasferito su un'altra piattaforma che supporta solo ANSI C e non supporta la openfunzione.

Secondo me la linea che termina la traduzione più spesso ti ostacola che ti aiuta, e l'analisi di fscanfè così debole che inevitabilmente finisci per lanciarla a favore di qualcosa di più utile.

E la maggior parte delle piattaforme che supportano C hanno una openfunzione.

Questo lascia la domanda di buffering. Nei luoghi in cui stai principalmente leggendo o scrivendo un file in sequenza, il supporto del buffering è davvero utile e migliora notevolmente la velocità. Ma può portare ad alcuni problemi interessanti in cui i dati non finiscono nel file quando ci si aspetta che siano lì. Devi ricordare fcloseo fflushal momento opportuno.

Se stai effettuando ricerche ( fsetposovvero fseekil secondo o il secondo è leggermente più complicato da utilizzare in modo conforme agli standard), l'utilità del buffering diminuisce rapidamente.

Certo, il mio pregiudizio è che tendo a lavorare molto con socket, e lì c'è il fatto che vuoi davvero fare IO non bloccante (che FILE *non riesce a supportare in modo ragionevole) senza alcun buffering e spesso i requisiti di analisi complessi colorano davvero le mie percezioni.


4
Non metterò in discussione le tue esperienze, ma mi piacerebbe sentirti elaborare un po 'su questo. Per quale tipo di applicazioni ritieni che il buffering integrato si frapponga? Qual è esattamente il problema?
Emil H,

1
Non ho visto l'ultimo paragrafo. Punto valido, IMHO. Per quanto posso dire, però, la domanda riguardava il file IO.
Emil H,

7
Per chiarire quando il buffering si mette in mezzo. È quando usi la ricerca. Il seguente lettura con qualunque comando ( fgets, fgetc, fscanf, fread), sarà sempre leggere l'intera dimensione del buffer (4K, 8K o qualsiasi altra cosa si imposta). Utilizzando l'I / O diretto è possibile evitarlo. In tal caso è ancora meglio usare al preadposto di una coppia cerca / leggi (1 syscall invece di 2).
Patrick Schlüter,

2
La gestione interrotta read()e le write()chiamate sono un quinto motivo conveniente per utilizzare la famiglia di funzioni libc.
nccc,

3
@ m-ric: Beh, questa è una domanda in qualche modo non correlata, ma sì. Tutte le piattaforme che supportano supportano ioctlanche la filenochiamata che accetta un FILE *e restituisce un numero che può essere utilizzato in una ioctlchiamata. Stai attento però. FILE *le chiamate correlate possono interagire in modo sorprendente con l'utilizzo ioctlper modificare qualcosa del descrittore di file sottostante.
Onnipotente,

53

open()è una chiamata os di basso livello. fdopen()converte un descrittore di file di livello os nell'astrazione FILE di livello superiore del linguaggio C. fopen()chiama open()in background e ti dà direttamente un puntatore FILE.

Ci sono molti vantaggi nell'usare oggetti FILE piuttosto che descrittori di file grezzi, che include una maggiore facilità d'uso ma anche altri vantaggi tecnici come il buffering incorporato. Soprattutto il buffering generalmente comporta un notevole vantaggio in termini di prestazioni.


3
Ci sono degli svantaggi nell'utilizzo delle versioni bufferizzate di 'f ...' di open?
LJM,

5
@L. Moser, sì, quando si stanno già eseguendo il buffering dei dati, e quindi il buffer aggiuntivo aggiunge la copia non necessaria e l'overhead della memoria.
Michael Aaron Safyan,

6
in realtà ci sono altri svantaggi. fopen()non fornisce lo stesso livello di controllo durante l'apertura dei file, ad esempio creare autorizzazioni, modalità di condivisione e altro. tipicamenteopen() e le varianti offrono un controllo molto maggiore, vicino a quello che effettivamente fornisce il sistema operativo
Matt Joiner,

2
Ci sono anche casi estremi in cui si fa mmapil file e si effettuano modifiche con I / O normale (per quanto incredibile sembriamo effettivamente nel nostro progetto e per ottime ragioni), il buffering sarebbe di ostacolo.
Patrick Schlüter

Potresti anche voler usare altre funzioni di sistema, come usare open () per precaricare i file nella cache della pagina tramite readahead (). Immagino che la regola empirica sia "usa fopen a meno che tu non abbia assolutamente bisogno di open ()", open () in realtà ti consente di fare cose fantasiose (impostare / non impostare O_ATIME e simili).
Tomas Pruzina,

34

fopen vs open in C

1) fopenè una funzione di libreria mentre openè una chiamata di sistema .

2) fopenfornisce IO bufferizzato che è più veloce rispetto al openquale non è bufferizzato .

3) fopenè portatile mentre opennon portatile ( open è specifico per l'ambiente ).

4) fopenrestituisce un puntatore a una struttura FILE (FILE *) ; openrestituisce un numero intero che identifica il file.

5) A FILE *ti dà la possibilità di usare fscanf e altre funzioni stdio.


9
openè uno standard POSIX, quindi è abbastanza portatile
osvein

12

A meno che tu non faccia parte dello 0,1% delle applicazioni in cui l'utilizzo openè un reale vantaggio in termini di prestazioni, non c'è davvero alcun buon motivo per non utilizzarlo fopen. Per quanto fdopenriguarda, se non stai giocando con i descrittori di file, non hai bisogno di quella chiamata.

Stick fopene la sua famiglia di metodi ( fwrite, fread, fprintf, et al) e sarete molto soddisfatti. Altrettanto importante, altri programmatori saranno soddisfatti del tuo codice.


11

Se avete una FILE *, è possibile utilizzare funzioni come fscanf, fprintfe fgetsecc Se si dispone solo il descrittore di file, si hanno limitato (ma probabilmente più veloce) routine di ingresso e di uscita read, writeetc.


7

L'uso di open, read, write significa che devi preoccuparti delle interazioni dei segnali.

Se la chiamata è stata interrotta da un gestore di segnale, le funzioni restituiranno -1 e imposteranno errno su EINTR.

Quindi sarebbe il modo corretto di chiudere un file

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

4
Per close, questo dipende dal sistema operativo. Non è corretto eseguire il loop su Linux, AIX e altri sistemi operativi.
Strcat,

Inoltre, l'uso di lettura e scrittura subirà lo stesso problema, cioè possono essere interrotti da un segnale prima di elaborare interamente l'input / output e il programmatore deve gestire tali situazioni, mentre fread e fwrite gestiscono bene le interruzioni del segnale.
Marcelo,

6

open()è una chiamata di sistema specifica per i sistemi basati su Unix e restituisce un descrittore di file. È possibile scrivere su un descrittore di file utilizzando write()quale è un'altra chiamata di sistema.
fopen()è una chiamata di funzione ANSI C che restituisce un puntatore a file ed è portabile su altri sistemi operativi. Possiamo scrivere su un puntatore a file usandofprintf .

In Unix:
puoi ottenere un puntatore di file dal descrittore di file usando:

fP = fdopen(fD, "a");

È possibile ottenere un descrittore di file dal puntatore del file utilizzando:

fD = fileno (fP);

4

open () verrà chiamato alla fine di ciascuna delle funzioni della famiglia fopen () . open () è una chiamata di sistema e fopen () sono forniti dalle librerie come funzioni wrapper per la facilità d'uso dell'utente


2

Ho cambiato in open () da fopen () per la mia applicazione, perché fopen causava doppie letture ogni volta che eseguivo fopen fgetc. Le doppie letture sono state dirompenti per quello che stavo cercando di realizzare. open () sembra proprio fare ciò che gli chiedi.


2

Dipende anche da quali flag sono richiesti per aprire. Per quanto riguarda l'uso per la scrittura e la lettura (e la portabilità) f * dovrebbe essere usato, come discusso sopra.

Ma se fondamentalmente vuoi specificare più di flag standard (come flag rw e append), dovrai usare un'API specifica per la piattaforma (come POSIX open) o una libreria che astratti questi dettagli. Lo standard C non ha tali flag.

Ad esempio, potresti voler aprire un file, solo se esce. Se non si specifica il flag di creazione, il file deve esistere. Se aggiungi esclusivo per creare, creerà il file solo se non esiste. Ce ne sono molti altri.

Ad esempio sui sistemi Linux è presente un'interfaccia LED esposta tramite sysfs. Espone la luminosità del led attraverso un file. Scrivere o leggere un numero come una stringa compresa tra 0 e 255. Ovviamente non vuoi creare quel file e scriverlo solo se esiste. La cosa bella adesso: usa fdopen per leggere / scrivere questo file usando le chiamate standard.


0

aprendo un file usando fopen
prima di poter leggere (o scrivere) informazioni da (a) un file su un disco dobbiamo aprire il file. per aprire il file abbiamo chiamato la funzione fopen.

1.firstly it searches on the disk the file to be opened.
2.then it loads the file from the disk into a place in memory called buffer.
3.it sets up a character pointer that points to the first character of the buffer.

questo il modo di comportarsi della funzione fopen
ci sono alcune cause durante il processo di buffering, potrebbe essere scaduto. pertanto, confrontando fopen (I / O di alto livello ) con la chiamata di sistema aperta (I / O di basso livello), è più veloce e più appropriato di fopen .


è aperto più velocemente di fopen?
Obayhan,

sì, aperta è la chiamata di sistema, che è più veloce di fopen - comparativamente @obayhan
prashad
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.