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()
.
.
.