• Non ci sono risultati.

19 - Input/Output su File Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo

N/A
N/A
Protected

Academic year: 2022

Condividi "19 - Input/Output su File Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo"

Copied!
35
0
0

Testo completo

(1)

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

(2)

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

(3)

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

(4)

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

(5)

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

(6)

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

(7)

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

(8)

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

(9)

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

(10)

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

(11)

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 );

} } }

(12)

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

(13)

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

(14)

( 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

(15)

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

(16)

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

(17)

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

(18)

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

(19)

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

(20)

( 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

(21)

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

(22)

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

(23)

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

(24)

( 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

(25)

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

(26)

( 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

(27)

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

(28)

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

(29)

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

(30)

( 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

(31)

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

(32)

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

(33)

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

(34)

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

(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

Riferimenti

Documenti correlati

Ogni area della schermata principale di Eclipse ` e detta Vista (View) La vista centrale ci consentira di scrivere il nostro programma La vista “Package Explorer” (a sinistra)

• Regola 3: Anche se le stringhe di formato della scanf() assomigliano molto a quelle della printf(), hanno una semantica leggermente differente (leggete il manuale!). • Regola

Il numero di figli di ogni nodo di un albero pu` o essere fiassato o variabile Quando il numero dei figli di ogni nodo ` e fissato a 2, l’albero si dice binario (come

Nella dichiarazione di una variabile se ne specifica il nome e il tipo (o meglio, il tipo dei valori che pu` o contenere). Nell’esempio, abbiamo dichiarato tre variabili con nomi

La guardia pu` o essere una qualunque espressione booleana Il comando (o blocco) ` e detto corpo del do-while. Semantica

• FileOutputStream implementa questi metodi nel caso parti- colare in cui l’output è un file, il cui nome è passato al costrut- tore di FileOutputStream ; in alternativa si

This example assumes that TESTFILE is a file with a few lines of data written to it using the Write # statement; that is, each line contains a string in quotations and a

o implementare una funzione virtuale nella classe base implementata nelle classi derivate (con output). o implementare una funzione virtuale nella classe base non implementata