From: Simone Piccardi Date: Sun, 25 Nov 2001 23:17:21 +0000 (+0000) Subject: Fatte fopen, freopen, fdopen X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=ccf26588d42ef932ab19587f8ca2c974a417bb49;ds=sidebyside Fatte fopen, freopen, fdopen --- diff --git a/filestd.tex b/filestd.tex index b761d99..0ea9995 100644 --- a/filestd.tex +++ b/filestd.tex @@ -86,7 +86,7 @@ file \file{stdio.h}. Ai tre file descriptor standard (vedi \secref{sec:file_std_descr}) aperti per ogni processo, corrispondono altrettanti stream, che rappresentano i canali standard di input/output prestabiliti; anche questi tre stream sono -idetificabili attraverso dei nomi simbolici definiti nell'header +identificabili attraverso dei nomi simbolici definiti nell'header \file{stdio.h} che sono: \begin{itemize} @@ -140,7 +140,7 @@ tenere presente le caratteristiche delle operazioni di \textit{flush} dei dati, poiché non è detto che ad una scrittura sullo stream corrisponda una immediata scrittura sul dispositivo. -Per risondere ad esigenze diverse, lo standard definisce tre distinte modalità +Per rispondere ad esigenze diverse, lo standard definisce tre distinte modalità in cui può essere eseguita la bufferizzazione, delle quali occorre essere ben consapevoli, specie in caso di lettura e scrittura da dispositivi interattivi: \begin{itemize} @@ -200,9 +200,125 @@ analoghe a quelle di \secref{sec:file_base_func} per i file descriptor. In particolare vedremo come aprire, leggere, scrivere e cambiare la posizione corrente in uno stream. + \subsection{Apertura e chiusura di uno stream} \label{sec:file_fopen} +Le funzioni che permettono di aprire uno stream sono tre\footnote{\func{fopen} + e \func{freopen} fanno parte dello standard ANSI C, \func{fdopen} è parte +dello standard POSIX.1.}, i loro prototipi sono: + +\begin{functions} + \headdecl{stdio.h} + \funcdecl{FILE * fopen(const char * path, const char *mode)} + Apre il file specificato da \param{path}. + \funcdecl{FILE * fdopen(int fildes, const char * mode)} + Associa uno stream al file descriptor \param{fildes}. + \funcdecl{FILE * freopen(const char * path, const char * mode, FILE * + stream)} + Apre il file specificato da \param{path} associandolo allo stream + specificato da \param{stream}, se questo è già aperto prima lo chiude. + + Le funzioni ritornano un puntatore valido in caso di successo e \macro{NULL} + in caso di errore, in tal caso \var{errno} viene settata al valore ricevuto + dalla funzione sottostante di cui è fallita l'esecuzione. + + Gli errori pertanto possono essere quelli di \func{malloc} per tutte e tre + le funzioni, quelli \func{open} per \func{fopen}, quelli di \func{fcntl} per + \func{fdopen} e quelli di \func{fopen}, \func{fclose} e \func{fflush} per + \func{freopen}. +\end{functions} + +Normalmente la funzione che si usa per aprire uno stream è \func{fopen}, essa +apre il file specificato nella modalità specificata da \param{mode} che è una +delle stringhe elencate in \tabref{tab:file_fopen_mode}. + +L'uso di \func{freopen} è in genere per redirigere uno dei tre file standard +(vedi \secref{sec:file_std_stream}): il file \param{path} viene associato a +\param{stream} e se questo è uno stream aperto prima viene chiuso. + +Infine \func{fdopen} viene usato per associare uno stream ad un file +descriptor esistente ottenuto tramite una altra funzione (come \func{open}, +\func{dup}, \func{pipe}) e serve quando si vogliono usare gli stream con file +speciali come le fifo od i socket, che non possono essere aperti con le +funzioni delle librerie standard del C. + +\begin{table}[htb] + \centering + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Valore} & \textbf{Significato}\\ + \hline + \hline + \texttt{r} & Il file viene aperto in sola lettura; lo stream è posizionato + all'inizio del file.\\ + \texttt{r+} & Il file viene aperto in lettura e scrittura; lo stream è + posizionato all'inizio del file. \\ +% \hline + \texttt{w} & Il file viene troncato a lunghezza nulla (o creato se non + esiste), ed aperto in sola lettura; lo stream è posizionato all'inizio del + file.\\ + \texttt{w+} & Il file viene troncato a lunghezza nulla (o creato se non + esiste), ed aperto in scrittura e lettura; lo stream è posizionato + all'inizio del file.\\ +% \hline + \texttt{a} & Il file è aperto in \textit{append mode} in sola scrittura + (o creato se non esiste). \\ + \texttt{a+} & Il file è aperto in \textit{append mode} in lettura e + scrittura (o creato se non esiste). \\ + \hline + \end{tabular} + \caption{Modalità di apertura di uno stream} + \label{tab:file_fopen_mode} +\end{table} + +In realtà lo standard ANSI C prevede un totale di 15 possibili valori diversi +per \param{mode}, ma in \tabref{tab:file_fopen_mode} si sono riportati solo i +sei valori effettivi, ad essi può essere aggiunto pure il carattere \func{b} +(come ultimo carattere o nel mezzo agli altri per le stringhe di due +caratteri) che in altri sistemi operativi serve a distinguere i file binari +dai file di testo; in un sistema POSIX questa distinzione non esiste e il +valore viene accettato solo per compatibilità, ma non ha alcun effetto. + +Inoltre nel caso si usi \func{fdopen} i valori specificati da \param{mode} +devono essere compatibili con quelli con cui il file descriptor è stato +aperto. Inoltre i modi \cmd{w} e \cmd{w+} non troncano il file. La posizione +nello stream viene settata a quella corrente nel file descriptor, e le +variabili di errore e di fine del file sono cancellate. Il file non viene +duplicato e verrà chiuso alla chiusura dello stream. + +I nuovi file saranno creati secondo quanto visto in +\secref{sec:file_ownership} ed avranno i permessi di accesso settati al valore +\macro{S\_IRUSR|S\_IWUSR|S\_IRGRP|S\_IWGRP|S\_IROTH|S\_IWOTH} (pari a +\macro{0666}) modificato secondo il valore di \acr{umask} per il processo (si +veda \secref{sec:file_umask}). + +In caso di file aperti in lettura e scrittura occorre ricordarsi che c'è di +messo una bufferizzazione; per questo motivo lo standard ANSI C richiede che +ci sia una operazione di posizionamento fra una operazione di output ed una di +input o viceversa (eccetto il caso in cui l'input ha incontrato la fine del +file), altrimenti una lettura può ritornare anche il risultato di scritture +precedenti l'ultima effettuata. + +Per questo motivo è una buona pratica (e talvolta necessario) far seguire ad +una scrittura una delle funzioni \func{fflush}, \func{fseek}, \func{fsetpos} o +\func{rewind} prima di eseguire una rilettura; viceversa nel caso in cui si +voglia fare una scrittura subito dopo aver eseguito una lettura occorre prima +usare una delle funzioni \func{fseek}, \func{fsetpos} o \func{rewind}. Anche +una operazione nominalmente nulla come \func{fseek(file, 0, SEEK\_CUR)} è +sufficiente a garantire la sincronizzazione. + +Uno stream viene chiuso con la funzione \func{fclose} il cui prototipo è: +\begin{prototype}{stdio.h}{int fclose(FILE * stream)} + Chiude lo stream \param{stream}. + + Restituisce 0 in caso di successo e \macro{EOF} in caso di errore, nel qual + caso setta \var{errno} a \macro{EBADF} se il file descriptor indicato da + \param{stream} non è valido, o uno dei valori specificati dalla sottostante + funzione che è fallita (\func{close}, \func{write} o \func{fflush}). +\end{prototype} + + \subsection{Lettura e scrittura su uno stream} \label{sec:file_io} @@ -224,10 +340,6 @@ corrente in uno stream. \label{sec:file_formatted_io} -\subsection{Chiusura di uno stream} -\label{sec:file_fclose} - - \section{Funzioni avanzate} \label{sec:file_stream_adv_func}