19 - Input/Output su File
Programmazione e analisi di dati Modulo A: Programmazione in Java
Paolo Milazzo
Dipartimento di Informatica, Universit`a di Pisa http://www.di.unipi.it/milazzo
milazzo di.unipi.it
Corso di Laurea Magistrale in Informatica Umanistica A.A. 2019/2020
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 1 / 35
Nei programmi visti fino ad ora abbiamo usato
Output su schermo(tramite System.out.println()) Input da tastiera(tramite la classe Scanner)
Con queste modalit`a di Input/Output, al termine dell’esecuzione di un programma tutti i dati inseriti tramite tastiera vengono persi
Spesso `e utile fornire funzionalit`a dipersistenzadei dati
i dati devono poter sopravvivere alla terminazionedel programma ed essere disponibili in una successiva nuova esecuzione
bisogna salvarei dati in unfile
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 2 / 35
Stream (1)
In Java, l’Input/Output su file segue il modello degli stream(oflussi) Uno stream di input prevede unasorgente di dati(es. un file) che possono essere utilizzati da un programma
Uno stream di outputprevede unadestinazione per i dati(es. un file) che sono generati da un programma
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 3 / 35
Volendo fare un’analogia:
Uno stream di input `e come l’acquedotto pubblico, che porta l’acqua da una sorgente al rubinetto di casa
Uno stream di output `e come il sistema fognario, che porta l’acqua dal rubinetto di casa al depuratore
Quando si apre un rubinetto, l’acqua continua a uscire fintanto che:
non chiudiamo il rubinetto
non si esaurisce l’acqua della sorgente
Analogamente, in uno stream di input si continua a ricevere dati fintanto che:
non si decide di smettere di leggerli
la sorgente dei dati si esaurisce (es. il file `e finito)
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 4 / 35
Stream (3)
In Java, le classi di libreria per la gestione degli stream si dividono in due gruppi:
per la gestione distream di caratteri per la gestione distream di bytes Nel caso dei file:
le classi del primo gruppo consentono di leggere/scriverefile di testo le classi del secondo gruppo consentono di leggere/scrivere file binari (immagini, video, dati, ecc...)
I file di testo possono essere modificati con un qualunque programma di scrittura, i file binari no!
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 5 / 35
Le classi di base per la gestione degli stream consentono di leggere/scrivere
singoli caratteri singoli bytes
Tali classi sono le seguenti:
Stream di caratteri: FileReader e FileWriter
Stream di bytes: FileInputStream e FileOutputStream Queste classi (come le classi che vedremo nel seguito) fanno parte del package java.io
devono essere importate nei programmi!
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 6 / 35
Stream basici (2)
Vediamo il funzionamento degli stream di caratteri gli stream di bytes funzionano in maniera analoga
La classe FileReaderconsente di leggere un file un carattere alla volta Per fare ci`o dobbiamo:
1. passare al costruttoredi FileReader il nome del file (come stringa) 2. chiamare ripetutatmenteil metodo read() che legge un carattere 3. chiuderelo stream invocando il metodo close()
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 7 / 35
Pi`u in dettaglio:
Chiamata del costruttore:
F i l e R e a d e r r e a d e r = new F i l e R e a d e r (" p r o v a . txt ");
predispone il file per la lettura (interagendo con il sistema operativo del computer)
lancia un’eccezione se il file non esiste Lettura dei singoli caratteri:
int n e x t = r e a d e r . r e a d ();
restituisce -1 se il file `e terminato
altrimenti l’intero pu`o esserecastato a char e usato nel programma Chiusura dello stream:
r e a d e r . c l o s e ();
libera la risorsa: comunica al sistema operativo del computer che il file pu`o essere usato da altri programmi
Stream basici (3)
Le operazioni sugli stream coinvolgono pesantemente il sistema operativo del computer, e non solo!
Ad esempio: quando si esegue una read()
La Java Virtual Machine fa la richiesta del carattere alfile system (componente del sistema operativo che gestisce i file)
Il file system a sua volta fa una opportuna richiesta aldriver del disposivo di memorizzazione relativo (disco fisso, chiavetta USB,...) Il driver invia opportuni segnali aldispositivo di memorizzazione stesso Il dispositivo di memorizzazione recupera il dato e lo rimanda indetro ai richiedenti
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 9 / 35
Molti componenti esternialla Java Virtual Machine sono coinvolti
`
e relativamente probabileche qualcosa vada storto...
per tutelarsi, Java utilizza le eccezionidi tipoIOException tali eccezioni:
I possono essere lanciate datutti i metodidelle classi di gestione degli stream
I sonocontrollate: ossia,devono essere gestiteda chi chiama i metodi
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 10 / 35
Esempio: Lettura di un file
i m p o r t j a v a . io . F i l e R e a d e r ; i m p o r t j a v a . io . I O E x c e p t i o n ; p u b l i c c l a s s L e g g i F i l e {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [] a r g s ) { try {
int n e x t ;
// c r e a lo s t r e a m di i n p u t
F i l e R e a d e r r e a d e r = new F i l e R e a d e r (" p r o v a . txt ");
do {
// l e g g e i c a r a t t e r i n e x t = r e a d e r . r e a d ();
if ( n e x t != -1) {
// c a s t a l ’ i n t e r o a c h a r e lo v i s u a l i z z a c h a r c = (c h a r) n e x t ;
S y s t e m . out . p r i n t ( c );
}
} w h i l e ( n e x t != -1); // f i n c h e il f i l e non f i n i s c e // c h i u d e lo s t r e a m
r e a d e r . c l o s e ();
}
c a t c h ( I O E x c e p t i o n e ) {
// in c a s o di e r r o r i in una d e l l e o p e r a z i o n i ...
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
} } }
La scrittura su file tramite uno stream di output `e analoga alla lettura:
Si utilizza la classe FileWriter
Al posto di read() si usa il metodo write()
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 12 / 35
Esempio: Copia di un file (1)
i m p o r t j a v a . io . F i l e R e a d e r ; i m p o r t j a v a . io . F i l e W r i t e r ; i m p o r t j a v a . io . I O E x c e p t i o n ; p u b l i c c l a s s C o p i a F i l e {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [] a r g s ) {
// q u e s t o non s e r v e ... lo uso s o l o per c a l c o l a r e // il t e m p o di e s e c u z i o n e del p r o g r a m m a
l o n g i n i z i o = S y s t e m . c u r r e n t T i m e M i l l i s ();
try { int n e x t ;
// c r e a e n t r a m b i gli s t r e a m ( i n p u t e o u t p u t ) F i l e R e a d e r r e a d e r = new F i l e R e a d e r (" p r o v a . txt ");
F i l e W r i t e r w r i t e r = new F i l e W r i t e r (" p r o v a 2 . txt ");
do {
// l e g g e un c a r a t t e r e d a l l o s t r e a m di i n p u t ...
n e x t = r e a d e r . r e a d ();
if ( n e x t != -1) {
c h a r c = (c h a r) n e x t ;
// e lo s c r i v e n e l l o s t r e a m di o u t p u t ...
w r i t e r . w r i t e ( c );
}
} w h i l e ( n e x t != -1); // f i n c h e ’ il f i l e non f i n i s c e ( s e g u e )
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 13 / 35
( s e g u e C o p i a F i l e )
// c h i u d e e n t r a m b i gli s t r e a m r e a d e r . c l o s e ();
w r i t e r . c l o s e (); // p r o v a r e a c o m m e n t a r e q u e s t o !!
}
c a t c h ( I O E x c e p t i o n e ) { // in c a s o di e r r o r i ...
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
}
// q u a n t o t e m p o ha i m p i e g a t o ?
// ( a n c h e q u e s t o in r e a l t a ’ non s e r v e . . . ) l o n g f i n e = S y s t e m . c u r r e n t T i m e M i l l i s ();
S y s t e m . out . p r i n t l n (" I m p i e g a t i "+( fine - i n i z i o )+" m i l l i s e c o n d i ");
} }
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 14 / 35
Input/Output bufferizzato (1)
Leggere o scrivere un carattere per volta richiede tempo...
per ogni carattere bisogna ripetere tutti i passaggicon il sistema operativo descritti prima
il programma CopiaFile richiedediversi millisecondi (che non `e poco) anche per copiare file di piccola dimensione...
La soluzione a questo problema `e l’utilizzo di unbuffer
Un buffer `e una memoria tampone usata per immagazzinare dati da usare in seguito
Ritornando all’analogia dell’acquedotto, un buffer `e simile a:
I Unariserva d’acqua(nei posti a rischio di siccit`a) [input]
I Unboiler(mantiene un po’ di acqua calda pronta per l’uso) [input]
I Unafossa biologica(raccoglie i liquami prodotti) [output]
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 15 / 35
Uno stream bufferizzatolo si ottiene utilizzando uno stream basico all’interno di una opportuna classe
Di nuovo, le classi per la creazione di stream bufferizzati si differenziano a seconda del tipo di stream:
Stream di caratteri: BufferedReader e BufferedWriter
Stream di bytes: BufferedInputStream e BufferedOutputStream Vediamo ancora il caso dello stream di caratteri (il caso dei bytes `e analogo)
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 16 / 35
Input/Output bufferizzato (3)
Per usare uno stream di input bufferizzato (l’output `e analogo) dobbiamo:
1. passare al costruttoredi BufferedReader uno stream basico (di tipo FileReader)
2. chiamare ripetutatmenteil metodo read() che legge un carattere 3. chiuderelo stream invocando il metodo close()
Rispetto allo stream basico cambia solo la chiamata al costruttore Il BufferedReader viene collegato a un FileReader...
... come una riserva idrica viene collegata a un rubinetto dell’acqua Il FileReader spesso viene creato al momento
B u f f e r e d R e a d e r r e a d e r =
new B u f f e r e d R e a d e r (new F i l e R e a d e r (" p r o v a . txt "));
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 17 / 35
Continueremo a leggere un carattere per volta, ma di nascosto il BufferedReader si porter`a avanti con il lavoro:
quando si esegue una read() vengono richiesti al sistema operativo un numero di caratteri pari alla dimensione del buffer
successive chiamatea read() verranno subito risoltedal buffer senza interpellare il sistema operativo
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 18 / 35
Esempio: Copia di un file (1)
// N O T A : c o s i ’ i m p o r t a t u t t e le c l a s s i del p a c k a g e j a v a . io i m p o r t j a v a . io .*;
p u b l i c c l a s s C o p i a F i l e B u f f e r i z z a t o { p u b l i c s t a t i c v o i d m a i n ( S t r i n g [] a r g s ) {
// q u e s t o non s e r v e ... lo uso s o l o per c a l c o l a r e // il t e m p o di e s e c u z i o n e del p r o g r a m m a
l o n g i n i z i o = S y s t e m . c u r r e n t T i m e M i l l i s ();
try { int n e x t ;
// c r e a e n t r a m b i gli s t r e a m b u f f e r i z z a t i B u f f e r e d R e a d e r r e a d e r =
new B u f f e r e d R e a d e r (new F i l e R e a d e r (" p r o v a . txt "));
B u f f e r e d W r i t e r w r i t e r =
new B u f f e r e d W r i t e r (new F i l e W r i t e r (" p r o v a 2 . txt "));
do {
// l e g g e un c a r a t t e r e d a l l o s t r e a m di i n p u t ...
n e x t = r e a d e r . r e a d ();
if ( n e x t != -1) {
c h a r c = (c h a r) n e x t ;
// e lo s c r i v e n e l l o s t r e a m di o u t p u t ...
w r i t e r . w r i t e ( c );
}
} w h i l e ( n e x t != -1); // f i n c h e ’ il f i l e non f i n i s c e ( s e g u e )
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 19 / 35
( s e g u e C o p i a F i l e B u f f e r i z z a t o )
// c h i u d e e n t r a m b i gli s t r e a m r e a d e r . c l o s e ();
w r i t e r . c l o s e ();
}
c a t c h ( I O E x c e p t i o n e ) { // in c a s o di e r r o r i ...
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
}
// q u a n t o t e m p o ha i m p i e g a t o ?
// ( a n c h e q u e s t o in r e a l t a ’ non s e r v e . . . ) l o n g f i n e = S y s t e m . c u r r e n t T i m e M i l l i s ();
S y s t e m . out . p r i n t l n (" I m p i e g a t i "+( fine - i n i z i o )+" m i l l i s e c o n d i ");
} }
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 20 / 35
Input/Output formattato (1)
Leggere singoli caratteri non `e il massimo...
esistono classi che si occupano di dare una formaai dati letti/scritti tramite uno stream
Nel caso degli stream di caratteritali classi di formattazione sono Scanner per formattare i dati di uno stream di input
PrintWriterper formattare i dati di uno stream di output Sono in realt`a sono classi analoghe a quelle gi`a usateper input/output tramite tastiera/video!
Scanner fornisce nextInt(), nextLine(), ecc..
PrintWriter fornisce println() e print()
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 21 / 35
Come usare Scanner con i file:
1. passare al costruttoredi Scanner uno stream di caratteri di input (meglio se bufferizzato, BufferedReader)
2. usare i metodi nextInt(), nextLine(), ecc... per leggere dal file facendo attezione
I bisogna esseresicuridel tipo di valore che si legge con questi metodi
I o, in alternativa, bisogna esserepronti a gestirel’eccezione lanciata in caso di input di tipo sbagliato
3. chiudere lo Scanner
Come usare PrintWriter con i file:
1. passare al costruttoredi PrintWriter uno stream di caratteri di output (meglio se bufferizzato, BufferedWriter)
2. usare i metodi println() e print() per scrivere nel file 3. chiudere il PrintWriter
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 22 / 35
Esempio: registro delle eta’ (1)
// N O T A : c o s i ’ i m p o r t o t u t t e le c l a s s i del p a c k a g e j a v a . io i m p o r t j a v a . io .*;
i m p o r t j a v a . u t i l . S c a n n e r ; i m p o r t j a v a . u t i l . V e c t o r ;
p u b l i c c l a s s R e g i s t r o E t a M i n i m a l e {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [] a r g s ) {
// m e m o r i z z a n o m i ed eta in due v e t t o r i " p a r a l l e l i ": al n o m e // in p o s i z i o n e i c o r r i s p o n d e l ’ eta ’ in p o s i z i o n e i
Vector < String > n o m i = new Vector < String > ( ) ; Vector < Integer > eta = new Vector < Integer > ( ) ; try {
// c r e a lo s t r e a m ( f o r m a t t a t o ) di i n p u t S c a n n e r f i l e _ i n p u t =
new S c a n n e r (new B u f f e r e d R e a d e r ( new F i l e R e a d e r (" r e g i s t r o . txt ") ) ) ;
// l e g g e t u t t o il file , a g g i u n g e n d o i v a l o r i l e t t i ai v e t t o r i w h i l e ( f i l e _ i n p u t . h a s N e x t ()) {
// n o t a : n o m e d e v e e s s e r e una s i n g o l a p a r o l a ( usa n e x t ) n o m i . add ( f i l e _ i n p u t . n e x t ( ) ) ;
eta . add ( f i l e _ i n p u t . n e x t I n t ( ) ) ; }
( s e g u e )
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 23 / 35
( s e g u e R e g i s t r o E t a M i n i m a l e ) // c h i u d e lo s t r e a m f i l e _ i n p u t . c l o s e ();
}
c a t c h ( I O E x c e p t i o n e ) { // in c a s o di e r r o r i ...
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
}
// s t a m p a il c o n t e n u t o del r e g i s t r o ( i v e t t o r i ) S y s t e m . out . p r i n t l n (" R E G I S T R O D E L L E ETA ’ ");
for (int i =0; i < n o m i . s i z e (); i ++) {
S y s t e m . out . p r i n t l n ( n o m i . get ( i ) + " " + eta . get ( i ));
}
S y s t e m . out . p r i n t l n ();
( s e g u e )
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 24 / 35
Esempio: registro delle eta’ (3)
( s e g u e R e g i s t r o E t a M i n i m a l e )
// c o n s e n t e di i n c r e m e n t a r e ( di uno ) l ’ eta ’ di a l c u n e // p e r s o n e nel r e g i s t r o
b o o l e a n f i n i t o = f a l s e; do {
// l e g g e un n o m e
S c a n n e r i n p u t = new S c a n n e r ( S y s t e m . in );
S y s t e m . out . p r i n t l n (" I n s e r i s c i un n o m e per i n c r e m e n t a r e l ’ eta ");
S y s t e m . out . p r i n t l n (" o p p u r e i n v i o per t e r m i n a r e : ");
S t r i n g n = i n p u t . n e x t L i n e ();
// se l ’ u t e n t e ha p r e m u t o i n v i o si f e r m a if ( n . e q u a l s (" ")) f i n i t o =t r u e;
e l s e {
// a l t r i m e n t i i n c r e m e n t a l ’ eta ’ c o r r i s p . al n o m e ( se p r e s e n t e ) int j = n o m i . i n d e x O f ( n );
if ( j == -1)
S y s t e m . out . p r i n t l n (" N o m e "+ n +" non p r e s e n t e nel r e g i s t r o ");
e l s e {
int e = eta . get ( j );
eta . set ( j , e + 1 ) ;
S y s t e m . out . p r i n t l n (" Ora " + n + " ha " + ( e +1) + " a n n i ");
} }
} w h i l e (! f i n i t o );
( s e g u e )
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 25 / 35
( s e g u e R e g i s t r o E t a M i n i m a l e )
// q u a n d o l ’ u t e n t e ha t e r m i n a t o , s a l v a t u t t o nel f i l e try {
// c r e a lo s t r e a m ( f o r m a t t a t o ) di o u t p u t P r i n t W r i t e r f i l e _ o u t p u t =
new P r i n t W r i t e r (new B u f f e r e d W r i t e r ( new F i l e W r i t e r (" r e g i s t r o . txt ") ) ) ; // s c r i v e i v a l o r i u s a n d o p r i n t l n
for (int i =0; i < n o m i . s i z e (); i ++) {
f i l e _ o u t p u t . p r i n t l n ( n o m i . get ( i ) + " " + eta . get ( i ));
}
// c h i u d e lo s t r e a m di o u t p u t f i l e _ o u t p u t . c l o s e ();
}
c a t c h ( I O E x c e p t i o n e ) { // in c a s o di e r r o r i ...
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
} } }
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 26 / 35
Serializzazione degli oggetti (1)
Sebbene le classi Scanner e PrintWriter aiutino a salvare dati di vario tipo su file, il loro uso non `e sempre facile
Quando abbiamo un programma complessoche usa molte strutture dati, salvare lo stato del programma in un file pu`o diventare complicato
In questi casi, l’implementazione di meccanismi di persistenza dei dati pu`o essere semplificata tramite
laserializzazione degli oggetti
La serializzazione degli oggetti `e una funzionalit`a di Java che consente di rappresentare oggetti arbitrariamente complessi come sequenze di byteben definite
tali sequenze di byte potranno essere salvate su filetramite uno stream (di byte, questa volta)
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 27 / 35
Per leggere/scrivere un oggetto in un file bisogna usare le classi:
ObjectInputStream e ObjectOutputStream
Nel caso di ObjectInputStream (l’output `e analogo) si procede come segue:
1. passare al costruttoredi ObjectInputStream uno stream di bytesdi input (meglio se bufferizzato, BufferedInputStream)
2. usare il metodoreadObject() per leggere dal filefacendo attenzione
I se il file non contiene un oggetto viene lanciata l’eccezione ClassNotFoundException
3. chiuderelo stream
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 28 / 35
Esempio: salvare un vettore (1)
i m p o r t j a v a . io .*;
i m p o r t j a v a . u t i l . V e c t o r ;
p u b l i c c l a s s S e r i a l i z z a V e t t o r e {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [] a r g s ) { // c r e a e i n i z i a l i z z a un v e t t o r e
Vector < String > v1 = new Vector < String > ( ) ; v1 . add (" AAA ");
v1 . add (" BBB ");
v1 . add (" CCC ");
// lo s a l v a in un f i l e try {
// n o t a r e le c l a s s i d e g l i s t r e a m di b y t e O b j e c t O u t p u t S t r e a m out =
new O b j e c t O u t p u t S t r e a m (new B u f f e r e d O u t p u t S t r e a m ( new F i l e O u t p u t S t r e a m (" s e r i a l i z z a . dat ") ) ) ; out . w r i t e O b j e c t ( v1 );
out . c l o s e ();
} c a t c h( I O E x c e p t i o n e ) {
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
} ( s e g u e )
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 29 / 35
( s e g u e S e r i a l i z z a V e t t o r e )
// lo r i l e g g e dal f i l e ( a s s e g n a n d o l o a un a l t r a v a r i a b i l e ) Vector < String > v2 = n u l l;
try {
// n o t a r e le c l a s s i d e g l i s t r e a m di b y t e O b j e c t I n p u t S t r e a m in =
new O b j e c t I n p u t S t r e a m (new B u f f e r e d I n p u t S t r e a m ( new F i l e I n p u t S t r e a m (" s e r i a l i z z a . dat ") ) ) ; v2 = ( Vector < String >) in . r e a d O b j e c t ();
in . c l o s e ();
} c a t c h ( C l a s s N o t F o u n d E x c e p t i o n e ) {
// se il f i l e non c o n t i e n e un o g g e t t o . . . .
S y s t e m . out . p r i n t l n (" P R O B L E M A ( m a n c a o g g e t t o nel f i l e ) ");
S y s t e m . out . p r i n t l n ( e );
} c a t c h( I O E x c e p t i o n e ) {
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
}
// s t a m p a q u a n t o l e t t o dal f i l e S y s t e m . out . p r i n t l n ( v2 );
} }
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 30 / 35
Serializzazione degli oggetti (3)
Affinch´e un oggetto possa essere serializzato e salvato su file, la sua classe deve implementare l’interfaccia Serializable
Tale interfaccia non prevede metodi
questo meccanismo serve solo per fardichiarare al programmatore che autorizzail salvataggio dei suoi oggetti
e’ un meccanismo disicurezza: la serializzazione mette a nudo (nel file) il contenuto delle variabili private di un oggetto!
un programmatore malevolo potrebbe accedere alle variabili private di un oggetto salvandolo su file e andando a leggere il file un byte alla volta....
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 31 / 35
Tutte le principali classi della Libreria di Java sono serializzabili (implementano Serializable)
ovviamente, devono essere serializzabili anche le classi degli oggetti in esse contenute
ad esempio:
I La classe String implementa Serializable, quindi un vettore di stringhe `e ok
I Un vettore di elementi di un tipo Rettangolo definito da noi `e serializzabile solo se Rettangolo lo `e
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 32 / 35
Serializzazione degli oggetti (5)
Alle classi che implementano Serializable viene richiesto (anche se non
`
e obbligatorio) di includere una costante statica serialVersionUID (di tipo long)
servirebbe per distinguere tra diverse versioni della stessa classe (es.
modifiche successive)
Rendiamo la classe Rettangolo serializzabile:
p u b l i c c l a s s R e t t a n g o l o i m p l e m e n t s S e r i a l i z a b l e { s t a t i c f i n a l l o n g s e r i a l V e r s i o n U I D = 1;
p u b l i c int b a s e ; p u b l i c int a l t e z z a ;
p u b l i c R e t t a n g o l o (int base , int a l t e z z a ) { t h i s. b a s e = b a s e ;
t h i s. a l t e z z a = a l t e z z a ; }
}
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 33 / 35
In questo modo possiamo salvare su file un vettore di rettangoli:
. . . .
Vector < R e t t a n g o l o > v = new Vector < R e t t a n g o l o > ( ) ; v . add (new R e t t a n g o l o ( 1 0 , 1 0 ) ) ;
v . add (new R e t t a n g o l o ( 1 5 , 5 0 ) ) ; v . add (new R e t t a n g o l o ( 2 0 , 6 0 ) ) ; try {
O b j e c t O u t p u t S t r e a m out =
new O b j e c t O u t p u t S t r e a m (new B u f f e r e d O u t p u t S t r e a m ( new F i l e O u t p u t S t r e a m (" r e t t a n g o l i . dat ") ) ) ; out . w r i t e O b j e c t ( v );
out . c l o s e ();
} c a t c h( I O E x c e p t i o n e ) {
S y s t e m . out . p r i n t l n (" E R R O R E di I / O ");
S y s t e m . out . p r i n t l n ( e );
} . . . .
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 34 / 35
Serializzazione degli oggetti (7)
Un esempio pi`u completo di programma che utilizza le serializzazione degli oggetti per implementare un meccanismo di persistenza dei dati `e il programma RegistroEtaCompleto (vedere la pagina webdel corso) Tale programma prevede:
una classe NomeEta che associa un nome a una et`a
una classe RegistroEtaCompleto che contiene un vettore di oggetti NomeEta e diverse funzionalit`a
una classe GestioneRegistroEta che contiene un menu per accedere alle varie funzionalit`a di RegistroEtaCompleto
Paolo Milazzo (Universit`a di Pisa) Programmazione - File I/O A.A. 2019/2020 35 / 35