Sei sulla pagina 1di 30

Sessione 8

Input/Output

1
Linput/output in Java
Nei linguaggi di programmazione per input/ouput si intende tutto ci che ha a che fare con operazioni di lettura/scrittura su
risorse esterne al programma. Specificamente per input si intendono le operazioni di lettura da risorse esterne e per output
operazioni di scrittura sempre su risorse esterne. Tipicamente le risorse esterne sono file, database o pagine web.

In Java il concetto chiave legato allinput/output quello di stream di dati, o flusso di dati.

Le risorse, come ad esempio i file, sono delle sequenze di byte; leggere una risorsa significa far fluire i byte dalla risorsa verso il
nostro programma Java. In questo caso si dovr quindi aprire un InputStream, ovvero un flusso di dati di input (per il nostro
programma). Viceversa, scrivere una risorsa, equivale a far fluire i byte dal nostro programma verso la risorsa; in questo caso
dovremo quindi apire un OutputStream.

Le principali classi offerte dal JDK per la relativa gestione sono presenti allinterno del package java.io.

Se apriamo la JavaDoc relativa al package java.io possiamo subito osservare, a conferma di quanto appena detto, come molte
delle classi presenti nel package abbiano il suffisso OutputStream o InputStream nel loro nome.

2
In particolare nella gerarchia di classi offerte dal JDK per gestire gli stream di input e di ingresso, al livello radice troviamo due
classi che si chiamano appunto InputStream e OutputStream. Queste due classi sono specializzate da una serie di altre classi.
Ad esempio per la gestione specifica degli stream legati ad i file troviamo FileInputStream e FileOutputStream.

Analizziamo ora, con il consueto supporto dei video associati al corso, il seguente codice che legge un file preesistente e ne crea
uno nuovo come copia del primo:

package com.azienda.esempiCorso.sessione8;

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class EsempioFileStream {

public static void main(String[] args)


{
try
{
FileInputStream fis = new FileInputStream("C:/CorsoJava/resources/fileInput.txt");
FileOutputStream fos = new FileOutputStream("C:/CorsoJava/resources/copiaTest.txt");
byte[] buffer = new byte[1024];
int len = -1;
while ( (len = fis.read(buffer)) > 0 )
{
System.out.println("Letti " + len + " bytes");

3
fos.write(buffer,0,len);
System.out.println("Scritti " + len + " bytes");
}
fis.close();
fos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}

Output a video:
Letti 14 bytes
Scritti 14 bytes

Il codice appena mostrato legge il file di ingresso di nome fileInput.txt, presente nella directory
C:/CorsoJava/resources/sessione8, crea un nuovo file di nome copiaTest.txt, nella stessa directory e, copia il contenuto di
fileInput.txt allinterno di copiaTest.txt, dopo aver stampato a video delle informazioni relative ai bytes che vengono via via
letti da fileInput.txt e scritti in copiaTest.txt.

4
Come al solito analizziamo il codice guardando sia la JavaDoc delle classi utilizzate che il video relativo del corso.

Da notare:

il file fileInput.txt deve esistere nel percorso specificato (C:/CorsoJava/resources/sessione8) altrimenti il


costruttore new FileInputStream rilancia leccezione FileNotFoundException. Questo uno dei motivi per cui
abbiamo dovuto inserire il codice allinterno del blocco try/catch
anche il costruttore new FileOutputStream pu rilanciare delle eccezioni. Altro motivo per cui abbiamo usato il
blocco try/catch
i byte vengono letti dalloggetto fis di classe FileInputStream invocando il metodo read che copia i byte letti
nellarray di byte buffer e restituisce un numero intero che indica il numero di byte letti. Il numero di byte letti dal
metodo read viene salvato nella variabile dappoggio len. Quando la lettura del file termina, len sar uguale a -1 o a
0. Quindi la condizione len > 0 rappresenta la condizione per continuare a leggere il file di input (sono ancora
presenti byte da leggere)
i metodi close sia di InputStream che di OutputStream possono rilanciare eccezioni; altro motivo per cui abbiamo
dovuto utilizzare il blocco try/catch
Il codice appena analizzato potrebbe non essere molto efficiente, in termini di memoria utilizzata, quando leggiamo e scriviamo
file di grandi dimensioni.

5
Quando si ha a che fare con file di grandi dimensioni (pi in generale con qualunque risorsa esterna di grandi dimensioni) pu
essere pi performante, in termini di memoria RAM utilizzata dal codice, bufferizzare le operazioni di lettura e scrittura;
ovvero, non mantenere in memoria RAM tutti i byte dei file che leggiamo e/o scriviamo ma leggere una piccola quantit di byte
alla volta. In questi casi conviene utilizzare le classi BufferedInputStream e BufferedOutputStream.

Vediamo lesempio precedente riscritto con lutilizzo delle classi BufferedInputStream e BufferedOutputStream:

package com.azienda.esempiCorso.sessione8;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class EsempioBufferedFileStream {

public static void main(String[] args)


{
try
{
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("C:/CorsoJava/resources/sessione8/fileInput.txt"));

6
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:/
CorsoJava/resources/sessione8/copiaTest.txt"));
byte[] buffer = new byte[1024];
int len = -1;
while ( (len = bis.read(buffer)) > 0 )
{
System.out.println("Letti " + len + " bytes");
bos.write(buffer,0,len);
System.out.println("Scritti " + len + " bytes");
}
bis.close();
bos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}

Output a video:
Letti 14 bytes
Scritti 14 bytes

7
I due esempi precedenti ci offrono lopportunit di mettere in risalto ancora una volta il concetto espresso nella sessione dedicata
alle Interfacce ed allereditariet:

immaginiamo di scrivere un metodo che effettui la copia di un file sorgente di input in un file di output. Nella firma del metodo
conviene dichiarare i parametri come oggetti delle superclassi InputStream e OutputStream, piuttosto che legarci ad una sotto-
classe specifica come ad esempio FileInputStream o FileOutputStream. Ovvero:

public void copiaFile(InputStream input,OutputStream output)

Questo ci consente di poter decidere nella classe chiamante il tipo di stream che vogliamo usare senza cambiare il codice del
metodo copiaFile.

Esempio:

package com.azienda.esempiCorso.sessione8;

import java.io.InputStream;
import java.io.OutputStream;

public class EsempioFileStream2


{
public void copiaFile(InputStream input,OutputStream output)
{
try
{

8
byte[] buffer = new byte[1024];
int len = -1;
while ( (len = input.read(buffer)) > 0 )
{
System.out.println("Letti " + len + " bytes");
output.write(buffer,0,len);
System.out.println("Scritti " + len + " bytes");
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

package com.azienda.esempiCorso.sessione8;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

9
public class UtilizzoEsempioFileStream2
{
public static void main(String args[])
{
try
{
EsempioFileStream2 oggetto = new EsempioFileStream2();
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("C:/CorsoJava/resources/sessione8/fileInput.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("C:/CorsoJava/resources/sessione8/copiaTest.txt"));
oggetto.copiaFile(bis,bos);
bis.close();
bos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}

Output a video:
Letti 14 bytes

10
Scritti 14 bytes

Nella classe chiamante UtilizzoEsempioFileStream2 decidiamo che tipo di stream passare al metodo copiaFile della classe
EsempioFileStream2. Se volessimo cambiare tipo di stream cambieremmo solo il codice del chiamante, ma limplementazione
del metodo copiaFile non cambierebbe.

Da notare che le chiusure degli stream tramite le chiamate ai metodi close vengono fatte nella classe chiamante. Questa una
tecnica molto comune: il metodo copiaFile lavora a stream aperti, ovvero si aspetta che gli stream vengano creati (aperti) e
successivamente chiusi dal chiamante. Come detto, questa una tecnica molto diffusa in Java che ritroveremo anche nellutilizzo
di altri tipi di risorse come i database.

Classi FileReader, BufferedReader, FileWriter e BufferedWriter

Gli esempi che abbiamo visto precedentemente consentono di lavorare con file di qualsiasi genere. Esistono infatti tantissimi tipi
di file: file di testo, file di immagini, file contenenti sia testo che immagini, file audio, file video, file codificati nelle forme pi
disparate. In ogni caso tutti questi tipi di file, in Java, possono essere sempre gestiti con le classi FileInputStream e
FileOutputStream.

11
Soltanto i file che contengono esclusivamente testo possono essere letti/scritti tramite le classi FileReader e FileWriter, e con le
stesse considerazioni fatte negli esempi precedenti a proposito dellottimizzazione dellutilizzo della memoria, le classi
BufferedReader e BufferedWriter, che mettono a disposizione dei metodi specifici per i file testuali.

Vediamo subito un esempio:

package com.azienda.esempiCorso.sessione8;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;

public class EsempioFileReaderWriter {

public static void main(String[] args)


{
try
{
BufferedReader bufferedReader = new BufferedReader(new
FileReader("C:/CorsoJava/resources/sessione8/fileInput.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new
FileWriter("C:/CorsoJava/resources/sessione8/fileOutput.txt"));
String line = null;

12
while ( ( line = bufferedReader.readLine() ) != null )
{
System.out.println("Letta la linea: " + line);
bufferedWriter.write(line);
}
bufferedReader.close();
bufferedWriter.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

Loutput a video:
Letta la linea: Ciao, come va?

Da notare le chiamate ai metodi read e write rispettivamente di BufferedReader e BufferedWriter: adesso si possono leggere
direttamente stringhe al posto di byte.

13
Unaltra classe che viene utilizzata quando si scrive su stream di puro testo (e che come vedremo nella parte web del corso
molto utilizzata nelle applicazioni Java web) PrintWriter.

Per la classe PrintWriter valgono le stesse considerazioni fatte negli esempi precedenti per BufferedWriter, con laggiunta di
ulteriori metodi di utilit.

Vediamo un esempio nel seguente codice:

package com.azienda.esempiCorso.sessione8;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;

public class EsempioPrintWriter {

public static void main(String[] args)


{
try
{
BufferedReader bufferedReader = new BufferedReader(new
FileReader("C:/CorsoJava/resources/sessione8/fileInput.txt"));

14
PrintWriter printWriter = new PrintWriter(new
FileWriter("C:/CorsoJava/resources/sessione8/fileOutput.txt"));
String line = null;
while ( ( line = bufferedReader.readLine() ) != null )
{
System.out.println("Letta la linea: " + line);
printWriter.println(line);
}
bufferedReader.close();
printWriter.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

Output a video:
Letta la linea: Ciao, come va?

Da notare nellesempio precedente che il file creato fileOutput.txt conterr una riga vuota in pi rispetto allo stesso file
generato tramite gli esempi di codice illustrati precedentemente. Ci dovuto alla chiamata al metodo println della classe

15
PrintWriter che oltre a scrivere sullo stream (il file fileOutput.txt nel nostro caso) la stringa che gli viene passata come
parametro, aggiunge anche un carattere di a capo automatico o in gergo informatico carriage return new line (ritorno del
carrello per similitudine con le vecchie stampanti usate prima della diffusione dei computer). Se si vuole evitare la nuova linea
generata tramite il carattere carriage return, si pu utilizzare il metodo print in luogo di println.

Classe File

Una classe che offre numerosi metodi di utilit quando si lavora con i file e con le directory la classe File che troviamo sempre
nel package java.io.

La classe File, tra le altre cose, permette di recuperare il nome di un file o di una directory, il path di un file o di una directory,
controllare se si sta lavorando su di un file o su di una directory, creare un file o una directory, cancellare un file o una directory,
recuperare il contenuto di una directory in termini di file e sottodirectory contenute nella directory.

Vediamo subito un esempio, come al solito guardando anche la JavaDoc della classe File e il video del corso::

package com.azienda.esempiCorso.sessione8;

import java.io.File;

16
public class EsempioFile {

public static void main(String[] args)


{
try
{
File file = new File("C:/CorsoJava/resources/sessione8/fileInput.txt");
System.out.println(file.getName() + " un file? " + file.isFile());
System.out.println(file.getName() + " una directory? " + file.isDirectory());
System.out.println("Il percorso di " + file.getName() + " " + file.getPath());
System.out.println("La directory in cui contenuto il file " + file.getName() + " " + file.getParent());
File dir = new File("C:/CorsoJava/resources/sessione8");
System.out.println(dir.getName() + " un file? " + dir.isFile());
System.out.println(dir.getName() + " una directory? " + dir.isDirectory());
File subDir = new File(dir.getPath() + File.separator + "subDir");
subDir.mkdir();
System.out.println("Creata la sotto-directory " + subDir.getPath());
File file2 = new File(subDir.getPath() + File.separator + "newFile.txt");
file2.createNewFile();
System.out.println("Creato nuovo file " + file2.getPath());
File file3 = File.createTempFile("prefisso_",".txt",subDir);
String oldNameFile3 = file3.getPath();
System.out.println("Creato nuovo file " + oldNameFile3);
File newFile3 = new File(file3.getParent() + File.separator + "file3.txt");
file3.renameTo(newFile3);
System.out.println("Rinominato " + oldNameFile3 + " in " + newFile3.getPath());

17
System.out.println("\nStampa della directory " + dir);
stampaDirectory(dir);
System.out.println("\nStampa della directory " + file);
stampaDirectory(file);
System.out.println("\nCancelliamo " + file2.getName());
file2.delete();
System.out.println("\nStampa della directory dopo la cancellazione");
stampaDirectory(dir);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

private static void stampaDirectory(File directory)


{
if ( directory.isDirectory() )
{
File[] items = directory.listFiles();
for ( int i=0; i<items.length; i++ )
{
File item = items[i];
String tipo = item.isFile() ? " File -> " : " Directory -> ";
System.out.println(tipo + item);
if ( item.isDirectory() )

18
{
stampaDirectory(item);
}
}
}
else
{
System.out.println(directory.getName() + " non una directory");
}
}
}
Output a video:
fileInput.txt un file? true
fileInput.txt una directory? false
Il percorso di fileInput.txt C:\CorsoJava\resources\sessione8\fileInput.txt
La directory in cui contenuto il file fileInput.txt C:\CorsoJava\resources\sessione8
sessione8 un file? false
sessione8 una directory? true
Creata la sotto-directory C:\CorsoJava\resources\sessione8\subDir
Creato nuovo file C:\CorsoJava\resources\sessione8\subDir\newFile.txt
Creato nuovo file C:\CorsoJava\resources\sessione8\subDir\prefisso_260079376107333808.txt
Rinominato C:\CorsoJava\resources\sessione8\subDir\prefisso_260079376107333808.txt in
C:\CorsoJava\resources\sessione8\subDir\file3.txt

Stampa della directory C:\CorsoJava\resources\sessione8


File -> C:\CorsoJava\resources\sessione8\copiaTest.txt
File -> C:\CorsoJava\resources\sessione8\fileInput.txt
File -> C:\CorsoJava\resources\sessione8\fileOutput.txt
Directory -> C:\CorsoJava\resources\sessione8\subDir

19
File -> C:\CorsoJava\resources\sessione8\subDir\file3.txt
File -> C:\CorsoJava\resources\sessione8\subDir\newFile.txt

Stampa della directory C:\CorsoJava\resources\sessione8\fileInput.txt


fileInput.txt non una directory

Cancelliamo newFile.txt

Stampa della directory dopo la cancellazione


File -> C:\CorsoJava\resources\sessione8\copiaTest.txt
File -> C:\CorsoJava\resources\sessione8\fileInput.txt
File -> C:\CorsoJava\resources\sessione8\fileOutput.txt
Directory -> C:\CorsoJava\resources\sessione8\subDir
File -> C:\CorsoJava\resources\sessione8\subDir\file3.txt

Da notare che un oggetto di classe File rappresenta un file o una directory corrispondente al percoso su file system specificato
come parametro del costrutttore della classe.

Pertanto, alcuni metodi sono applicabili o meno sulloggetto a seconda se esso rappresenta un file o una directory. Ad esempio il
metodo mkdir() applicabile solo su di una directory. Per questo motivo si possono utilizzare i metodi isDirectory o isFile
per determinare se si sta lavorando su di una directory o su di un file.

Da notare anche lutilizzo delloperatore ternario condizione ? blocco_istruzioni1 : blocco_istruzioni2 che abbiamo discusso
nella sessione dedicata alle basi della sintassi Java; qui riepiloghiamo solo che equivale al costrutto if ( condizione )
blocco_istruzioni1 else blocco_istruzioni2.

20
Classe Properties

Un file di properties un file di testo contenente una serie di coppie chiave = valore. Concettualmente un file di properties
molto simile alle mappe di cui abbiamo gi parlato. Tuttavia, in Java, esiste una classe ad hoc pensata per gestire i file di
properties. Si tratta della classe Properties del package java.util.

Sostanzialmente la classe assomiglia molto alle mappe, ma aggiunge dei metodi di utilit specifici per leggere e scrivere un
oggetto di tipo Properties direttamente in un file.

Vediamo subito un esempio:

package com.azienda.esempiCorso.sessione8;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

public class EsempioProperties {

public static void main(String[] args)


{
try
{

21
FileInputStream fis = new FileInputStream("C:/CorsoJava/resources/sessione8/file.properties");
Properties properties = new Properties();
properties.load(fis);
stampa(properties);
properties.put("chiaveNuovaProprieta","valoreNuovaProprieta");
FileOutputStream fos = new FileOutputStream("C:/CorsoJava/resources/sessione8/nuovoFile.properties");
properties.store(fos,"commenti");
stampa(properties);
}
catch( Exception ex)
{
ex.printStackTrace();
}
}

private static void stampa(Properties properties)


{
Set<Object> keySet = properties.keySet();
Iterator<Object> keyIterator = keySet.iterator();
System.out.println("\nStampa delle properties");
while ( keyIterator.hasNext() )
{
String key = (String) keyIterator.next();
String value = properties.getProperty(key);
System.out.println("Chiave: " + key + "/ value: " + value);
}

22
}
}

Loutput prodotto a video:

Stampa delle properties


Chiave: chiave2/ value: valore2
Chiave: chiave1/ value: valore1

Stampa delle properties


Chiave: chiave2/ value: valore2
Chiave: chiaveNuovaProprieta/ value: valoreNuovaProprieta
Chiave: chiave1/ value: valore1

Il file file.properties inizialmente contiene le due coppie chiave1=valore e chiave2=valore2. Tramite il metodo load le 2 coppie
vengono automaticamente caricate nelloggetto properties. Successivamente viene stampato a video il contenuto delloggetto
properties; quindi viene aggiunta, via codice, una nuova coppia chiaveNuovaProprieta/valoreNuovaProprieta alloggetto
properties attraverso linvocazione del metodo put. Infine viene salvato il contenuto delloggetto properties nel file
nuovoFile.properties.

23
Nota sullutilizzo delle costanti e sulla visibilit delle variabili:

negli esempi appena mostrati possiamo notare come la directory su cui abbiamo lavorato, C:\CorsoJava\resources\sessione8,
stata scolpita nel codice, o come si dice in gergo cablata (dallinglese cabled); ovvero abbiamo scritto esplicitamente in ogni
classe degli esempi mostrati la stringa che identificava il percorso, o path, della directory C:\CorsoJava\resources\sessione8.
Questa in realt non considerata una best practice: cosa succederebbe se volessimo cambiare la directory di lavoro degli
esempi? Dovremmo entrare in tutte le classi e modificare la stringa C:\CorsoJava\resources\sessione8. Ecco lutilit delle
costanti: la best practice, in casi del genere, definire la suddetta stringa come una costante in un unico punto del codice, in modo
che in caso di modifiche dovremo modificare una sola riga di codice. La costante per essere inserita in un unico punto del codice
deve essere visibile da tutte le classi, ovvero deve avere una visibilit globale. La best practice in questi casi quella di definire
una classe in cui inserire le costanti globali e che queste ultime siano dichiarate public in questo modo:

public class Costanti {

public final static String path = C:\CorsoJava\resources\sessione8;

24
Serializzazione e de-serializzazione di oggetti
Per serializzazione, o marshalling, si intende loperazione di trasformazione di un oggetto in una sequenza di byte codificata
che possa essere salvata/inviata su di una risorsa esterna quale ad esempio un file, un database o una risorsa di rete.

La deserializzazione, o unmarshalling, loperazione inversa che ricostruisce un oggetto in memoria decodificando la sequenza
di byte che rappresenta loggetto su di una risorsa esterna.

Perch una classe Java possa essere serializzata deve dichiarare nella sua firma di implementare linterfaccia Serializable e deve
possedere attributi tutti serializzabili (ovvero a appartenenti a classi che implementano Serializable). Questultima
uninterfaccia offerta dal JDK che serve come semplice marcatore, ovvero per indicare che una classe serializzabile, ma
non dichiara alcun metodo, quindi non obbliga la classe concreta a dover implementare alcun metodo aggiuntivo.

ObjectOutputStream la classe del package java.io che ci consente di serializzare un oggetto su di una risorsa esterna
(OutputStream) tramite il metodo writeObject.

ObjectInputStream la classe del package java.io che ci consente di deserializzare un oggetto da una risorsa esterna
(InputStream) tramite il metodo readObject.

25
Vediamo subito un esempio che illustra tutti i concetti appena esposti:

package com.azienda.esempiCorso.sessione8.serializzazione;

import java.io.Serializable;

public class ClasseDaSerializzare implements Serializable


{
private static final long serialVersionUID = 1L;

private String stringa = null;


private Integer numero = null;

public ClasseDaSerializzare(String stringa,Integer numero)


{
setStringa(stringa);
setNumero(numero);
}

public String getStringa() {


return stringa;
}
public void setStringa(String stringa) {
this.stringa = stringa;
}
public Integer getNumero() {

26
return numero;
}
public void setNumero(Integer numero) {
this.numero = numero;
}

package com.azienda.esempiCorso.sessione8.serializzazione;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class UsoClasseDaSerializzare {

public static void main(String args[])


{
try
{

27
ClasseDaSerializzare oggettoDaSerializzare = new ClasseDaSerializzare("Ciao",new Integer(3));
System.out.println("Stampa oggetto prima della serializzazione");
stampa(oggettoDaSerializzare);
File file = new File("C:/CorsoJava/resources/sessione8/serializzazione.dat");
file.createNewFile();
serializzaOggetto(file,oggettoDaSerializzare);
ClasseDaSerializzare oggettoDeserializzato = deserializzaOggetto(file);
System.out.println("Stampa oggetto dopo la deserializzazione");
stampa(oggettoDeserializzato);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

private static void stampa(ClasseDaSerializzare oggettoDaSerializzare)


{
if ( oggettoDaSerializzare != null )
{
System.out.println("Stato oggetto: " + oggettoDaSerializzare.getStringa() + " - " +
oggettoDaSerializzare.getNumero());
}
}

private static void serializzaOggetto(File f,ClasseDaSerializzare oggettoDaSerializzare) throws Exception

28
{
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(fos));
oos.writeObject(oggettoDaSerializzare);
oos.close();
}

private static ClasseDaSerializzare deserializzaOggetto(File f) throws Exception


{
ClasseDaSerializzare oggettoClasseDaSerializzare = null;
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(f)));
oggettoClasseDaSerializzare = (ClasseDaSerializzare) ois.readObject();
ois.close();
return oggettoClasseDaSerializzare;
}

Output a video:

Stampa oggetto prima della serializzazione


Stato oggetto: Ciao - 3
Stampa oggetto dopo la deserializzazione
Stato oggetto: Ciao - 3

29
Da notare che:

loutput del programma non solo quello mostrato a video ma anche la creazione del file serializzazione.dat nella directory
C:/temp
la classe ClasseDaSerializzare implementa Serializable e le classi a cui appartengono i suoi attributi, ovvero String ed
Integer, anche implementano Serializable
il casting nellistruzione oggettoClasseDaSerializzare = (ClasseDaSerializzare) ois.readObject();. Infatti, il metodo
readObject, come si pu vedere dalla relativa JavaDoc, restituisce un oggetto di classe Object, ma come sappiamo tutte le
classi in Java estendono Object (e quindi anche la nostra classe ClasseDaSerializzare) e pertanto possibile effettuare il
casting (oltretutto noi sappiamo che loggetto ricostruito dallo stream deve essere di classe ClasseDaSerializzare altrimenti
otterremmo un errore in fase di esecuzione, a run-time)

30