*
* Ora parleremo dell'I/O, ossia Input/Output (Entrata/Uscita).
* Il sistema I/O del C ha un'interfaccia indipendente dall'hardware, ossia
* pone un certo livello di astrazione tra il programmatore e il dispositivo
* in uso, per cui e' analogo accedere a terminali, unita' a disco, a nastro
* eccetera. Benche' ogni dispositivo sia diverso dagli altri, vengono
* trasformati dall'ANSI C in un dispositivo logico chiamato FLUSSO.
* I tipi di flusso sono 2:
*
* 1) FLUSSO DI TESTO: e' una sequenza di caratteri, che pero' durante il
* trasferimento puo' subire anche delle conversioni secondo le necessita'
* dell'ambiente di destinazione (ad esempio il carattere di fine riga e'
* diverso in certi casi: puo' essere di newline o cr+lf) il che implica
* che il flusso eventualmente convertito puo' essere anche di dimensione
* diversa. Passando un file non di testo da questo flusso si danneggia!
*
* 2) FLUSSO BINARIO: e' una sequenza di byte avente una corrispondenza uno
* a uno con la sequenza rivevuta dal dispositivo esterno. Non avvenendo
* alcuna conversione il numero di byte scritti/letti rimane uguale.
*
* Abbiamo gia' visto comandi per I/O da e verso la console (tastiera/video),
* ossia printf/scanf, gets/puts, per leggere o scrivere stringhe e caratteri
* vari. A noi interessa maggiormente la lettura/scrittura nei FILE, in
* particolare su Hard Disk/Floppy, ad esempio nel caso volessimo salvare
* dei dati da un nostro programma, per poi rileggerli in un secondo momento
* per un nuovo utilizzo (file di preferenze settaggio, di dati ecc.).
* Veniamo quindi alla pratica: per leggere un file, le operazioni sono
* queste: "aprire" quel file con fopen(), leggerlo con fread(), e chiuderlo
* con fclose(). Una volta aperto un file (o piu' genericamente un flusso),
* otteniamo un PUNTATORE associato a quel file.
* Il PUNTATORE A UN FILE e' un vero e proprio puntatore, che punta ad
* informazioni sul file aperto, come il nome, lo stato e la posizione
* corrente. Un puntatore di file e' una variabile puntatore di tipo FILE:
*
* FILE *puntailfile
*
* In questo modo abbiamo creato un puntatore chiamato puntailfile adatto
* a contenere i dati di un file aperto con fopen in questo modo:
*
* puntailfile = fopen("nomefile", modalita');
*
* Dove nomefile e' il nome del file, ed eventualmente il path, e "modalita'"
* e' il modo di apertura desiderato (apertura di un file in lettura, oppure
* creazione di un file in scrittura, ad esempio).
* Ecco alcune delle modalita' piu' comuni:
*
* "rt" Apertura di un file di testo in lettura
* "wt" Creazione di un file di testo in scrittura
* "rb" Apertura di un file binario in lettura
* "wb" Creazione di un file binario in scrittura
*
* "rt" e "rb" servono per leggere un file esistente, "wt" e "wb" invece
* creano un file nuovo per scriverci qualcosa. Se esiste gia' un file
* con quel nome, viene sovrascritto. Due esempi di modo di apertura:
*
* puntailfile = fopen("c:\file.bau", "rb"); * file binario in lett.
* puntailfile = fopen("pippo.pip", "wt"); * file di testo in scritt.
*
* Dato che puo' verificarsi un errore nell'apertura, di solito si controlla:
*
* if ((puntailfile = fopen("pippo.pip", "rb"))==NULL) {
* puts("\nImpossibile aprire il file.\n");
* errore = 1 }
*
* Questo significa: se l'apertura del file fallisce, segna nella variabile
* errore il valore 1, che potra' in seguito essere controllato per sapere
* che il file non e' stato aperto. Altrimenti si potrebbe usare il return()
* con un valore particolare, o si fa terminare il programma.
* NULL e' un alias per 0, solitamente, e si usa per controllare se il
* puntatore e' rimasto NULL, ossia non inizializzato dopo l'apertura.
* Una volta aperto lo stream, si puo' leggere e scrivere con fread() e
* fwrite().
*
* Vediamo di mettere in pratica le ultime cose dette, leggendo questo
* file (clez6a.c) e facendone una copia, chiamata clez6a.bak.
* Se non trova il file, aggiungete il path.
* Ci serve di sapere qualche altra istruzione: fputc(), e' un putchar per
* i file, come si intuisce dal nome, e ci servira' per copiare un char
* alla volta da un file all'altro. Per sapere quanti char copiare, ossia
* quando finisce il primo file, possiamo usare feof().
* Attenzione che si scrive su HD/FD, io vi ho avvertito!
*/
#include <stdio.h> /* Includiamo la libreria standard */
/* Funzione principale e inizio del programma */
int main(void) /* Funzione principale, eseguita per prima */
{ /* Inizio della funzione main() */
int errore = 0; /* Variabile che uso per segnare eventuali errori */
FILE *leggoinput, *scrivooutput; /* Definisco 2 strutture FILE */
/* Provo ad aprire il file CLEZ6A.C in modalita' lettura file di testo */
if ((leggoinput = fopen("CLEZ6A.C", "rt")) == NULL) /* Se non si apre...*/
{
printf("\nNon posso aprire il file di input.\n");
errore=1; /* Segna l'errore */
}
if (errore==0) { /* Se non si e' verificato l'errore apro la dest. */
/* Provo ad aprire il file CLEZ6A.BAK in modalita' scrittura file di testo */
if ((scrivooutput = fopen("CLEZ6A.BAK", "wt")) == NULL) /* Si apre!? */
{
printf("\nNon posso aprire il file di output.\n");
errore=2; /* Uscita con errore */
}
}
if (errore==0) { /* Se non si e' verificato l'errore copio */
/* Se sono riuscito ad aprire entrambi i file, posso copiare il primo nel
secondo, char dopo char, fino alla fine. Per sapere quando sono arrivato
alla fine, uso feof(), che ritorna 0 finche' non si raggiunge la fine
del file (ossia EOF). Da notare l'operatore negazione "!". */
while (!feof(leggoinput)) /* Finche' NON siamo alla fine del file...*/
fputc(fgetc(leggoinput), scrivooutput); /* Copia 1 char alla volta */
}
/* File copiato, posso chiudere i due flussi (stream), sempre che sia
riuscito ad aprirli senza errori! */
if(errore!=1) fclose(leggoinput);
if(errore!=2) fclose(scrivooutput);
/* Scriviamo un messaggio di felicitazioni, o di rammarico per errore.*/
if(errore==0) printf("\nHo avuto successo!\n");
else printf("\nInsuccesso totale!\n");
return(0); /* la funzione main restituisce uno 0 intero */
} /* Fine della funzione main() */
/* Facile, no?
* In Java troveremo differenze di sintassi, ma la logica e' molto simile,
* a parte le limitazioni sulla scrittura, per motivi di sicurezza.
*/