4. Gestione di files testo_binari
Transcript
4. Gestione di files testo_binari
Gestione di files Motivazioni • Un programma in esecuzione legge (sequenzialmente) una sequenza di caratteri prodotti "al volo" dall'utente (tramite tastiera) • il programma in esecuzione scrive (sequenzialmente) una sequenza di caratteri sullo schermo (o stampante) Problema: – I dati in ingresso e i risultati prodotti sono "volatili“ – si potrebbe voler conservare i risultati prodotti (per usi futuri) – si potrebbe voler conservare i dati in ingresso (per poterli riutilizzare in una nuova esecuzione, .) Definizione di File • Un File è "insieme di dati" organizzati secondo una certa struttura, identificato da un nome, e memorizzato in memoria secondaria. FILE FILE DEFINIZIONE: E' una struttura di dati memorizzata su memoria di massa (nastro o disco). E' un insieme di record logici, dove un record è una struttura costituita da più dati anche non omogenei tra loro. Non c'è un limite al numero di record che possono essere contenuti nel file. • I tipi di files gestiti dal C++ sono: • File di testo (text file) inform. lette e scritte come caratteri (archivi con record a lunghezza variabile) • File binario (binary file) dati rappresentati secondo il formato interno della macchina. (archivi con record a lunghezza fissa) 1 • file di caratteri (testo): – costruito dall'utente usando un editor di testi – prodotto da un programma in esecuzione (p.es. risultati di un programma C++) La gestione dei file comprende varie operazioni: • Apertura si crea un collegamento tra la memoria centrale e il file che risiede sulla m. di massa • Lettura copia in memoria centrale i dati del file che si trovano nella m. di massa • Consultazione reperimento delle informazioni • Scrittura trasferimento nella memoria di massa dei dati che si trovano sulla m. centrale • Chiusura interrompe il collegamento tra m. centrale e memoria di massa. Lettura e scrittura in un file di testo • Scrittura su file (Output) • Lettura da file (Input) • Scrittura in coda ad un file (Append) Gestione di un file di testo (esercizio) 1. Creazione di un archivio con i nomi degli amici Il file fisico sarà “amici.dat” 2. Lettura del contenuto del file e stampa a video delle informazioni 3. Aggiunta di dati nel file esistente “amici.dat” in coda in modalità append 2 1. Creazione del file ed inserimento //creaamici.cpp: Creazione Archivio #include <iostream> #include <fstream> #include <string> using namespace std; nome fisico del file int main() { string nome; ofstream fout(“amici.dat”);// apertura in scrittura del file nome logico del file cout<<“Inserisci i nomi:”<<endl; cout<<“uno per riga(Ctr+Z per term)”<<end; while(cin>>nome) { fout<<nome<<endl; //scrive su file } fout.close(); //chiude file return 0; } 3 Approfondimento: Files in C++: dichiarazione Gestione dell'ingresso/uscita su file in un programma C++: • (1) includere la libreria <fstream> • (2) dichiarare (una o più) variabili di "tipo file“ (es. fstream file_dati; ) • tipi consentiti: – ifstream: variabile file di sola lettura – ofstream: variabile file di sola scrittura – fstream: variabile file di lettura/scrittura • (3) associare una variabile di tipo file a un oggetto di tipo file (tramite la funzione open()) (es. file_dati.open(“c:\Dati00.txt”); Ritorniamo all'esercizio.... 2. Lettura del file creato e stampa a video del contenuto //leggiamici.cpp: lettura del file creato e visualizzazione a video #include <iostream> #include <fstream> #include <string> using namespace std; int main() {string nome; ifstream fin(“amici.dat”);// apertura del file in lettura while(fin>>nome)//legge dal file fino alla fine { cout<<nome<<endl; //scrive a video nome } fin.close(); //chiude file Return 0; 4 } 3. Aggiunta di dati nel file esistente //aggiungiamici.cpp: aggiunta di nuovi nomi #include <iostream> #include <fstream> #include <string> using namespace std; int main() {string nome; ofstream fout(“amici.dat”, ios::app);// apertura del file in append cout<<“Inserisci nuovi nomi:”<<endl; cout<<“uno per riga(Ctr+Z per term)”<<end; while(cin>>nome) { fout<<nome<<endl; //scrive su file } fout.close(); //chiude file Return 0; } Apertura esplicita di un file ofstream fout; fout.open(“amici.dat”, ios::out); ifstream fin; fin.open(“amici.dat”, ios::in); ofstream fout; 5 fout.open(“amici.dat”, ios::app); Gestione errori su file Nei programmi che utilizzano file è opportuno aggiungere opportuni controlli per eventuali errori che si possono presentare durante l’APERTURA DEL FILE: • • FILE NON ESISTENTE ERRORE PER UN ACCESSO NON CORRETTO ALLA MEMORIA DI MASSA … Esistono due modalità Prima modalità If(!nomestream){ cout<<“Errore nell’apertura del file”<<endl;} Nell’esempio di lettura dell’archivio amici.dat if(!fin){ cout<<“Errore nell’apertura del file ”<<endl;} else { while(fin>>nome)//legge dal file fino alla fine { cout<<nome<<endl; //scrive a video nome } fin.close(); //chiude file } Return 0; 6 Seconda modalità viene usato il metodo fail() che restituisce true se si verifica un errore su file if(nomestream.fail()){ cout<<“Errore Errore nell’apertura del file ”<<endl;} else {…. } Controllo sulla fine del file 1° metodo while (fin>>variabile) 2° metodo Uso del metodo eof() Sintassi per uso eof() nomestream>> variabile while while(!nomestream.eof()) {cout<<variabile<<endl; nomestream>>variabile; } Esercizio: Gestione di una rubrica telefonica con nome e telefono attraverso un menù 7 la scrittura sulla rubrica avviene nome e telefono uno di seguito all’altro: archivio<<nome<<“ “<<telefono<<endl<<; //rubrica.cpp #include <iostream> #include <fstream> #include <string> using namespace std; const string NOMEARCH=“rubrica.dat”; //nome fisico dichiarato come costante fstream archivio; string nome, telefono; //Procedura che crea la rubrica Void crea() { archivio.open(NOMEARCH.c_str(),ios::out); cout<<“inserisci un nome *=fine):”; cin>>nome; while(nome!=“*”){ cout<<“Telefono:”; cin>>telefono; archivio<<nome<<“ “<<telefono<<endl; cout<<“inserisci un altro nome(*=fine)”; cin>>nome; } Archivio.close(); } Realizza la procedura : • • • 8 Aggiungi() che aggiunge un nome e un telefono Visualizza() che mostra il contenuto del file Ricerca() che dato un nome lo cerca e se presente stampa il telefono Soluzione #include <iostream> #include <fstream> #include <string> using namespace std; const string rubrica="rubrica.dat"; fstream archivio; string nome,cognome,tel; void crea() { archivio.open(rubrica.c_str(), ios::out); archivio.close(); } void aggiungi() { archivio.open(rubrica.c_str(), ios::app |ios::out); cout<<"inserisci cognome * per finire"<<endl; cin>>cognome; while(cognome!="*"){ cout<<"nome:"; cin>>nome; cout<<"Telefono:"; cin>>tel; archivio<<cognome<<" "<<nome<<" "<<tel<<endl; cout<<"inserisci un altro cognome(*=fine)"; cin>>cognome; } archivio.close(); } void visualizza() { archivio.open(rubrica.c_str(), ios::in); 9 while(archivio>>cognome>>nome>>tel){ cout<<cognome<<" "<<nome<<" "<<tel<<endl; } archivio.close(); } void ricerca(string c, string n) { bool trovato=false; archivio.open(rubrica.c_str(), ios::in); archivio>>cognome>>nome; while(!archivio.eof() && !trovato) {archivio>>tel; if((cognome==c)&&(nome==n)) { cout<<"contatto trovato con tel:"<<tel<<endl; trovato=true; } archivio>>cognome>>nome; } if(!trovato) cout<<"contatto inesistente!"; archivio.close(); } void menu() {cout<<"1 esci"<<endl; cout<<"2 aggiungi contatti"<<endl; cout<<"3 visualizza"<<endl; cout<<"4 ricerca"<<endl<<endl; } int main() {string co,no; 10 int scelta=10; crea(); while(scelta!=1) { menu(); cout<<"scelta="; cin>>scelta; cout<<endl; switch(scelta) { case 1: break; case 2: aggiungi(); break; case 3: visualizza(); break; case 4: cout<<"inserisci cognome e nome da cercare:"; cin>>co>>no; ricerca(co,no); break; } } return 0; } 11 File binari Accesso a file con record di lunghezza costante Struct Persona { int id; char nome[50];//nome e cognome Double stipendio; }; persona dipendente; Accesso a file binari... fstream nomestream; nomestream.open(nomefile,… ios::binary); Tipo di accesso a binary file: 1. Sequenziale scrivere o leggere dal primo record 2. Diretto posizionamento su uno specifico record Lettura e scrittura sequenziali su file binario • • nomestream.write(variabile, sizeof(variabile)); nomestream.read(variabile, sizeof(variabile)); Fare attenzione il metodo deve ricevere un puntatore a carattere per cui si effettua un casting sul record… nomestream.write(variabile, sizeof(variabile)); nomestream.read(variabile, sizeof(variabile)); Fare attenzione il metodo deve ricevere un puntatore a carattere per cui si effettua un casting sul record… SCRITTURA..... • nomestream.write((char*) &variabile, sizeof(variabile)); LETTURA..... • 12 nomestream.read((char*) &variabile, sizeof(variabile)); Creazione archivio dipendenti • • Costruisci un creadipendenti.cpp che apre il file binario in scrittura e lo richiude Il file fisico sarà anagrafe.dat Costruiamo ora un file inserisci dipendenti.cpp (in append) avendo inserito tutte le librerie e la definizione del record persona..... int main() { fstream fout; fout.open(“anagrafe.dat", ios::app | ios::binary); if (!fout) { cout<<“Error”<<endl; } else { cout<<“matricola dip(0 per finire) :”; cin>>dipendente.id; while(dipendente.id!=0) { cin.ignore(80,’\n’); cout<<“cognome e nome dip:”; cin.getline(dipendente.nome,50); cout<<“stipendio in euro:”; cin>>dipendente.stipendio; fout.write((char *) &dipendente, sizeof(dipendente)); cout<<“inserisci matricola nuovo dip (0 per finire): “; cin>>dipendente.id; } fout.close();} spiegazioni significative al codice: cin.ignore(80,’\n’);elimina il carattere di terminazione. Rimuove tutti i caratteri dal buffer di input fino a quando non 13 incontra il primo carattere newline. Il numero 80 indica il numero massimo di caratteri di una riga. Si mette dopo una lettura con cin>>. Elimina il carattere di terminazione per poter usare il metodo getline() di cin successivamente cin.getline(dipendente.nome,50) gestisce gli ingressi di stringhe di caratteri che possono avere anche spazi bianchi, si indica anche il numero massimo di caratteri L’operatore >> trascura gli spazi, le tabulazioni e i caratteri di fine riga Esercizio: Visualizza i dipendenti registrati Attività di progetto per il laboratorio: Le informazioni relative ai partecipanti alle gare studentesche di atletica vengono registrate in un archivio ad accesso sequenziale. 1. Costruire il file binario creaArchivioGS.cpp 2. Costruire una procedura che inserisce atleti nell’archivio 3. Costruire una procedura che stampi a video gli atleti registrati nell’archivio 4. Costruire una funzione che ci dica quanti 15enni partecipano alle gare. Il tutto deve prevedere un menù di scelta iterata Ricapitolando…..Metodi su file di testo e binari 14 operazioni Metodi/operatori File di testo . File binario . Apertura open() scrittura << scrittura write() . lettura read() . lettura >> . chiusura close() . . .