• Non ci sono risultati.

File e Flussi File e Flussi

N/A
N/A
Protected

Academic year: 2021

Condividi "File e Flussi File e Flussi"

Copied!
61
0
0

Testo completo

(1)

File e Flussi File e Flussi

C. Horstmann

C. Horstmann

Fondamenti di programmazione e Java 2

Fondamenti di programmazione e Java 2

3^ edizione Apogeo

3^ edizione Apogeo

trad. Nicola Fanizzi

trad. Nicola Fanizzi

corso di Programmazione, CdS: Informatica TPS

corso di Programmazione, CdS: Informatica TPS

Dip. di Informatica, Università degli studi di Bari

Dip. di Informatica, Università degli studi di Bari

(2)

2 2

Obiettivi Obiettivi

 Saper leggere e scrivere file di testo Saper leggere e scrivere file di testo

 Acquisire familiarità con i concetti di formato binario Acquisire familiarità con i concetti di formato binario e di testo

e di testo

 Capire la codifica cifrata delle informazioni Capire la codifica cifrata delle informazioni

 Capire quando va usato l’accesso casuale o Capire quando va usato l’accesso casuale o sequenziale ai file

sequenziale ai file

 Saper leggere e scrivere oggetti usando la Saper leggere e scrivere oggetti usando la serializzazione

serializzazione

(3)

3 3

Leggere e Scrivere File di Testo Leggere e Scrivere File di Testo

 Il modo più semplice per leggere file di testo prevede Il modo più semplice per leggere file di testo prevede l’utilizzo della classe

l’utilizzo della classe Scanner Scanner

 Per leggere dati da un file presente sul disco, Per leggere dati da un file presente sul disco, occorre dapprima costruire un oggetto di tipo occorre dapprima costruire un oggetto di tipo FileReader

FileReader

 Si utilizza tale oggetto come parametro per costruire Si utilizza tale oggetto come parametro per costruire un oggetto di tipo

un oggetto di tipo Scanner Scanner

 Per leggere i dati, si possono usare i metodi della classe: Per leggere i dati, si possono usare i metodi della classe:

FileReader reader = new FileReader("input.txt");

FileReader reader = new FileReader("input.txt");

Scanner in = new Scanner(reader);

Scanner in = new Scanner(reader);

(4)

4 4

Leggere e Scrivere File di Testo Leggere e Scrivere File di Testo

 Per scrivere file di testo usate la classe Per scrivere file di testo usate la classe PrintWriter

PrintWriter e i suoi metodi e i suoi metodi print print e e println

println

 Se il file in cui scrivere esiste già, Se il file in cui scrivere esiste già,

viene svuotato prima di scrivervi nuovi dati viene svuotato prima di scrivervi nuovi dati

 Se il file non esiste, Se il file non esiste,

viene creato un file vuoto viene creato un file vuoto

PrintWriter out = new PrintWriter("output.txt");

PrintWriter out = new PrintWriter("output.txt");

(5)

5 5

Leggere e Scrivere File di Testo Leggere e Scrivere File di Testo

 Usate, poi, i consueti metodi Usate, poi, i consueti metodi print print e e println println per inviare numeri, oggetti e stringhe all'istanza di per inviare numeri, oggetti e stringhe all'istanza di PrintWriter

PrintWriter

 Quando avete terminato di scrivere in un oggetto di Quando avete terminato di scrivere in un oggetto di tipo

tipo PrintWriter PrintWriter , accertatevi di chiuderlo , accertatevi di chiuderlo

 Se il programma termina l’esecuzione senza aver chiuso Se il programma termina l’esecuzione senza aver chiuso

out.println(29.95);

out.println(29.95);

out.println(new Rectangle(5, 10, 15, 25));

out.println(new Rectangle(5, 10, 15, 25));

out.println("Hello, World!");

out.println("Hello, World!");

out.close();

out.close();

(6)

6 6

Esempio di Programma Esempio di Programma

 Legge tutte le righe presenti in un file di dati in Legge tutte le righe presenti in un file di dati in ingresso e le invia ad un file di uscita,

ingresso e le invia ad un file di uscita,

facendo precedere a ciascuna riga di testo il facendo precedere a ciascuna riga di testo il

corrispondente numero di riga corrispondente numero di riga

 Se il file d’ingresso è: Se il file d’ingresso è:

Mary had a little lamb Mary had a little lamb

Whose fleece was white as snow.

Whose fleece was white as snow.

And everywhere that Mary went, And everywhere that Mary went, The lamb was sure to go!

The lamb was sure to go!

(7)

7 7

Esempio di programma Esempio di programma

 Allora il programma produce il seguente file: Allora il programma produce il seguente file:

 I numeri di riga sono racchiusi tra delimitatori I numeri di riga sono racchiusi tra delimitatori /* /*

*/ */ in modo che il programma possa essere in modo che il programma possa essere

utilizzato per numerare file di codice sorgente Java utilizzato per numerare file di codice sorgente Java

/* 1 */ Mary had a little lamb /* 1 */ Mary had a little lamb

/* 2 */ Whose fleece was white as snow.

/* 2 */ Whose fleece was white as snow.

/* 3 */ And everywhere that Mary went, /* 3 */ And everywhere that Mary went, /* 4 */ The lamb was sure to go!

/* 4 */ The lamb was sure to go!

(8)

8 8

LineNumberer.java LineNumberer.java

01: import java.io.FileReader;

01: import java.io.FileReader;

02: import java.io.IOException;

02: import java.io.IOException;

03: import java.io.PrintWriter;

03: import java.io.PrintWriter;

04: import java.util.Scanner;

04: import java.util.Scanner;

05: 05:

06: public class LineNumberer 06: public class LineNumberer 07: {

07: {

08: public static void main(String[] args) 08: public static void main(String[] args) 09: {

09: {

10: Scanner console = new Scanner(System.in);

10: Scanner console = new Scanner(System.in);

11: System.out.print("Input file: ");

11: System.out.print("Input file: ");

12: String inputFileName = console.next();

12: String inputFileName = console.next();

13: System.out.print("Output file: ");

13: System.out.print("Output file: ");

14: String outputFileName = console.next();

14: String outputFileName = console.next();

15: 15:

16: try 16: try 17: { 17: {

18: FileReader reader = new FileReader(inputFileName);

18: FileReader reader = new FileReader(inputFileName);

19: Scanner in = new Scanner(reader);

19: Scanner in = new Scanner(reader);

(9)

9 9

LineNumberer.java LineNumberer.java

22:

22:

23: while (in.hasNextLine()) 23: while (in.hasNextLine()) 24: {

24: {

25: String line = in.nextLine();

25: String line = in.nextLine();

26: out.println("/* " + lineNumber + " */ " + line);

26: out.println("/* " + lineNumber + " */ " + line);

27: lineNumber++;

27: lineNumber++;

28: } 28: } 29: 29:

30: out.close();

30: out.close();

31: } 31: }

32: catch (IOException exception) 32: catch (IOException exception) 33: {

33: {

34: System.out.println("Error processing file:"

34: System.out.println("Error processing file:"

+ exception);

+ exception);

35: }

35: }

36: }

36: }

(10)

10 10

Una Finestra di Dialogo

Una Finestra di Dialogo

(11)

11 11

Una Finestra di Dialogo Una Finestra di Dialogo

JFileChooser chooser = new JFileChooser();

JFileChooser chooser = new JFileChooser();

FileReader in = null;

FileReader in = null;

if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { File selectedFile = chooser.getSelectedFile(); { File selectedFile = chooser.getSelectedFile();

reader = new FileReader(selectedFile); reader = new FileReader(selectedFile);

. . . . . .

} }

(12)

12 12

Formato di Testo Formato di Testo

 Esistono due modi fondamentalmente diversi di Esistono due modi fondamentalmente diversi di memorizzare i dati:

memorizzare i dati:

 In formato testo In formato testo

 In formato binario In formato binario

(13)

13 13

Formato di Testo Formato di Testo

 Nel formato testo i dati sono rappresentati in una Nel formato testo i dati sono rappresentati in una forma leggibile dagli esseri umani come una

forma leggibile dagli esseri umani come una sequenza di caratteri

sequenza di caratteri

 Per esempio, il numero intero 12345 viene memorizzato Per esempio, il numero intero 12345 viene memorizzato come una sequenza di cinque caratteri:

come una sequenza di cinque caratteri:

'1' '2' '3' '4' '5' '1' '2' '3' '4' '5'

 Per elaborare dati in ingresso e in uscita dovete Per elaborare dati in ingresso e in uscita dovete usare le classi

usare le classi Reader Reader e e Writer Writer e le loro e le loro sottoclassi

sottoclassi

 Per leggere: Per leggere:

FileReader reader = new FileReader("input.txt");

FileReader reader = new FileReader("input.txt");

(14)

14 14

Formato Binario Formato Binario

 Nel formato binario i dati sono rappresentati da byte Nel formato binario i dati sono rappresentati da byte

 In formato binario il numero intero 12345 viene registrato In formato binario il numero intero 12345 viene registrato come una sequenza di quattro byte

come una sequenza di quattro byte 0 0 48 57 0 0 48 57

 Se memorizzate le informazioni in forma binaria, Se memorizzate le informazioni in forma binaria, come sequenza di byte, dovete usare le classi come sequenza di byte, dovete usare le classi InputStream

InputStream e e OutputStream OutputStream e le loro e le loro sottoclassi

sottoclassi

 La memorizzazione binaria è più compatta e più La memorizzazione binaria è più compatta e più efficiente

efficiente

(15)

15 15

Formato Binario Formato Binario

 Per leggere dati binari da un file su disco si crei un Per leggere dati binari da un file su disco si crei un oggetto di tipo

oggetto di tipo FileInputStream FileInputStream

 Si usi oggetti di tipo Si usi oggetti di tipo FileWriter FileWriter e e FileOutputStream

FileOutputStream per scrivere dati in un file per scrivere dati in un file su disco in forma di testo o, rispettivamente, binaria su disco in forma di testo o, rispettivamente, binaria

FileInputStream inputStream FileInputStream inputStream

= new FileInputStream("input.bin");

= new FileInputStream("input.bin");

FileOutputStream outputStream FileOutputStream outputStream

= new FileOutputStream("output.bin");

= new FileOutputStream("output.bin");

(16)

16 16

Leggere un Singolo Carattere da Leggere un Singolo Carattere da

un File in Formato Testo un File in Formato Testo

 La classe La classe Reader Reader ha un metodo, ha un metodo, read read , che , che legge un carattere alla volta

legge un carattere alla volta

 Il metodo Il metodo read read di fatto restituisce un dato di tipo di fatto restituisce un dato di tipo int int

 Alla fine dei dati, Alla fine dei dati, read read restituisce restituisce –1 –1

Reader reader = . . .;

Reader reader = . . .;

int next = reader.read();

int next = reader.read();

char c;

char c;

if (next != -1) if (next != -1) c = (char) next;

c = (char) next;

(17)

17 17

Leggere un Singolo Carattere da Leggere un Singolo Carattere da

un File in Formato Testo un File in Formato Testo

 La classe La classe InputStream InputStream ha un metodo ha un metodo read read per leggere un byte alla volta

per leggere un byte alla volta

 Restituisce un dato di tipo Restituisce un dato di tipo int int , che può essere il byte , che può essere il byte che è stato inserito

che è stato inserito

 Restituisce il numero intero Restituisce il numero intero –1 –1 , se è stata raggiunta la , se è stata raggiunta la fine del flusso

fine del flusso

InputStream in = . . .;

InputStream in = . . .;

int next = in.read();

int next = in.read();

byte b; if byte b; if (next != -1) (next != -1)

b = (byte) next;

b = (byte) next;

(18)

18 18

Formato Testo e Binario Formato Testo e Binario

 Le classi Le classi Writer Writer e e FileOutputStream FileOutputStream

hanno un metodo write per scrivere, rispettivamente, hanno un metodo write per scrivere, rispettivamente,

un singolo carattere o byte un singolo carattere o byte

 Questi metodi basilari sono gli unici metodi di lettura Questi metodi basilari sono gli unici metodi di lettura e scrittura forniti dalle classi che leggono e scrivono e scrittura forniti dalle classi che leggono e scrivono

un file un file

 Il pacchetto dei flussi di Java si basa sul principio Il pacchetto dei flussi di Java si basa sul principio che ciascuna classe deve avere una

che ciascuna classe deve avere una responsabilità responsabilità ben precisa

ben precisa

(19)

19 19

Formato Testo e Binario Formato Testo e Binario

 Il compito di un oggetto di tipo Il compito di un oggetto di tipo FileInputStream

FileInputStream è quello di interagire con i è quello di interagire con i file, cioè di acquisire dati sotto forma di byte, non di file, cioè di acquisire dati sotto forma di byte, non di

analizzarli analizzarli

 Se volete leggere numeri, stringhe o altri oggetti, Se volete leggere numeri, stringhe o altri oggetti, dovete combinare la classe con altre classi

dovete combinare la classe con altre classi

(20)

20 20

Un Programma di Crittografia Un Programma di Crittografia

 Il programma cifra un file Il programma cifra un file

 Mescola i dati in modo che siano illeggibili tranne per chi Mescola i dati in modo che siano illeggibili tranne per chi conosca il metodo di decifrazione e la corrispondente conosca il metodo di decifrazione e la corrispondente

parola segreta parola segreta

 Useremo un metodo che era conosciuto ai tempi di Useremo un metodo che era conosciuto ai tempi di Giulio Cesare

Giulio Cesare

 Si sceglie una chiave di cifratura, che in questo caso è un Si sceglie una chiave di cifratura, che in questo caso è un numero compreso tra 1 e 25

numero compreso tra 1 e 25

 Esempio Esempio

se la chiave è 3, si sostituisce A con D, B con E, e così via

se la chiave è 3, si sostituisce A con D, B con E, e così via

(21)

21 21

Un programma di crittografia Un programma di crittografia

Figura 2:

Il codice di Cesare

Testo normale

Testo cifrato

 Per la decifrazione, si usa semplicemente il valore Per la decifrazione, si usa semplicemente il valore opposto della chiave (negativo)

opposto della chiave (negativo)

(22)

22 22

Elaborazione di Dati Binari Elaborazione di Dati Binari

int next = in.read();

int next = in.read();

if (next == -1) done = true;

if (next == -1) done = true;

else else { {

byte b = (byte) next;

byte b = (byte) next; //call the method to encrypt the byte //call the method to encrypt the byte byte c = encrypt(b);

byte c = encrypt(b);

out.write(c); out.write(c);

} }

(23)

23 23

Encryptor.java Encryptor.java

01: import java.io.File;

01: import java.io.File;

02: import java.io.FileInputStream;

02: import java.io.FileInputStream;

03: import java.io.FileOutputStream;

03: import java.io.FileOutputStream;

04: import java.io.InputStream;

04: import java.io.InputStream;

05: import java.io.OutputStream;

05: import java.io.OutputStream;

06: import java.io.IOException;

06: import java.io.IOException;

07: 07:

08: /**

08: /**

09: un cifratore cifra file usando la crittyografia di Cesare.

09: un cifratore cifra file usando la crittyografia di Cesare.

10: Per la decifrazione, usate un cifratore con la chiave 10: Per la decifrazione, usate un cifratore con la chiave 11: opposta a quella di cifratura.

11: opposta a quella di cifratura.

12: */

12: */

13: public class Encryptor 13: public class Encryptor 14: {

14: {

15: /**

15: /**

16: Costruisce un cifratore.

16: Costruisce un cifratore.

(24)

24 24

Encryptor.java Encryptor.java

19: public Encryptor(int aKey) 19: public Encryptor(int aKey) 20: {

20: {

21: key = aKey;

21: key = aKey;

22: } 22: } 23: 23:

24: /**

24: /**

25: cifra il contenuto di un file.

25: cifra il contenuto di un file.

26: @param inFile il nome del file in ingresso 26: @param inFile il nome del file in ingresso 27: @param outFile il nome del file in uscita 27: @param outFile il nome del file in uscita 28: */

28: */

29: public void encryptFile(String inFile, String outFile) 29: public void encryptFile(String inFile, String outFile) 30: throws IOException

30: throws IOException 31: {

31: {

32: InputStream in = null;

32: InputStream in = null;

33: OutputStream out = null;

33: OutputStream out = null;

34: 34:

35: try

35: try

(25)

25 25

Encryptor.java Encryptor.java

37: in = new FileInputStream(inFile);

37: in = new FileInputStream(inFile);

38: out = new FileOutputStream(outFile);

38: out = new FileOutputStream(outFile);

39: encryptStream(in, out);

39: encryptStream(in, out);

40: } 40: }

41: finally 41: finally 42: {

42: {

43: if (in != null) in.close();

43: if (in != null) in.close();

44: if (out != null) out.close();

44: if (out != null) out.close();

45: } 45: } 46: }

46: } 47: 47:

48: /**

48: /**

49: Cifra il contenuto di un flusso.

49: Cifra il contenuto di un flusso.

50: @param in il flusso di ingresso 50: @param in il flusso di ingresso 51: @param out il flusso di uscuta 51: @param out il flusso di uscuta 52: */

52: */

(26)

26 26

Encryptor.java Encryptor.java

53: public void encryptStream(InputStream in, OutputStream 53: public void encryptStream(InputStream in, OutputStream out) out)

54: throws IOException 54: throws IOException 55: {

55: {

56: boolean done = false;

56: boolean done = false;

57: while (!done) 57: while (!done) 58: {

58: {

59: int next = in.read();

59: int next = in.read();

60: if (next == -1) done = true;

60: if (next == -1) done = true;

61: else 61: else 62: { 62: {

63: byte b = (byte) next;

63: byte b = (byte) next;

64: byte c = encrypt(b);

64: byte c = encrypt(b);

65: out.write(c);

65: out.write(c);

66: }

66: }

67: }

67: }

68: }

68: }

(27)

27 27

Encryptor.java Encryptor.java

70: /**

70: /**

71: Cifra un byte.

71: Cifra un byte.

72: @param b il byte da cifrare 72: @param b il byte da cifrare 73: @return il byte cifrato

73: @return il byte cifrato 74: */

74: */

75: public byte encrypt(byte b) 75: public byte encrypt(byte b) 76: {

76: {

77: return (byte) (b + key);

77: return (byte) (b + key);

78: } 78: } 79: 79:

80: private int key;

80: private int key;

81: }

81: }

(28)

28 28

EncryptorTester.java EncryptorTester.java

01: import java.io.IOException;

01: import java.io.IOException;

02: import java.util.Scanner;

02: import java.util.Scanner;

03: 03:

04: /**

04: /**

05: Un programma per collaudare il cifratore con 05: Un programma per collaudare il cifratore con

il codice di Cesare. il codice di Cesare.

06: */

06: */

07: public class EncryptorTester 07: public class EncryptorTester 08: {

08: {

09: public static void main(String[] args) 09: public static void main(String[] args) 10: {

10: {

11: Scanner in = new Scanner(System.in);

11: Scanner in = new Scanner(System.in);

12: try 12: try 13: { 13: {

14: System.out.print("Input file: ");

14: System.out.print("Input file: ");

15: String inFile = in.next();

15: String inFile = in.next();

16: System.out.print("Output file: ");

(29)

29 29

EncryptorTester.java EncryptorTester.java

18: System.out.print("Encryption key: ");

18: System.out.print("Encryption key: ");

19: int key = in.nextInt();

19: int key = in.nextInt();

20: Encryptor crypt = new Encryptor(key);

20: Encryptor crypt = new Encryptor(key);

21: crypt.encryptFile(inFile, outFile);

21: crypt.encryptFile(inFile, outFile);

22: } 22: }

23: catch (IOException exception) 23: catch (IOException exception) 24: {

24: {

25: System.out.println("Error processing file: "

25: System.out.println("Error processing file: "

+ exception);

+ exception);

26: } 26: } 27: } 27: } 28: } 28: } 29: 29:

30: 30:

(30)

30 30

Crittografia con Chiave Pubblica Crittografia con Chiave Pubblica

Figura 3

Vediamoci Vediamoci

alla festa alla festa in toga in toga

Testo normale

Testo normale testo testo

decifrato decifrato

Testo cifrato Testo cifrato

Chiave pubblica di Bob Chiave pubblica di Bob

chiave privata di chiave privata di

Bob Bob

Vediamoci Vediamoci

alla festa

alla festa

in toga

in toga

(31)

31 31

Accesso Casuale e Accesso Casuale e Accesso Sequenziale Accesso Sequenziale

 Accesso sequenziale Accesso sequenziale

 Un file viene elaborato un byte alla volta Un file viene elaborato un byte alla volta

 può essere poco efficiente può essere poco efficiente

 Accesso casuale Accesso casuale

 consente di accedere a posizioni arbitrarie nel file consente di accedere a posizioni arbitrarie nel file

 Solo i file su disco forniscono l’accesso casuale Solo i file su disco forniscono l’accesso casuale

System.in System.in e System.out e System.out non lo forniscono non lo forniscono

 Ciascun file su disco ha una posizione speciale detta Ciascun file su disco ha una posizione speciale detta puntatore del file

puntatore del file

(32)

32 32

Accesso Casuale Accesso Casuale e Accesso Sequenziale e Accesso Sequenziale

Accesso sequenziale

Accesso casuale

 Ciascun file su disco ha una posizione speciale detta Ciascun file su disco ha una posizione speciale detta puntatore del file

puntatore del file

 Potete scrivere e leggere nella posizione in cui si trova il Potete scrivere e leggere nella posizione in cui si trova il puntatore

puntatore

(33)

33 33

RandomAccessFile RandomAccessFile

 Potete aprire un file solo per: Potete aprire un file solo per:

 Leggere (“r”) Leggere (“r”)

 Leggere e scrivere (“rw”) Leggere e scrivere (“rw”)

L’invocazione del metodo sposta il puntatore al byte L’invocazione del metodo sposta il puntatore al byte

di indice n, contando le posizioni dall’inizio del file di indice n, contando le posizioni dall’inizio del file

RandomAccessFile f = new RandomAcessFile("bank.dat","rw");

RandomAccessFile f = new RandomAcessFile("bank.dat","rw");

f.seek(n);

f.seek(n);

(34)

34 34

RandomAccessFile RandomAccessFile

 Per sapere qual è la posizione corrente del puntatore Per sapere qual è la posizione corrente del puntatore del file userete

del file userete

 Per sapere qual è il numero dei byte di un file si usa Per sapere qual è il numero dei byte di un file si usa il metodo

il metodo length length

long n = f.getFilePointer();

long n = f.getFilePointer();

fileLength = f.length();

fileLength = f.length();

(35)

35 35

Esempio di Programma Esempio di Programma

 Usa un file ad accesso casuale per memorizzare un Usa un file ad accesso casuale per memorizzare un insieme di conti correnti

insieme di conti correnti

 Il programma di prova fa specificare un numero di Il programma di prova fa specificare un numero di conto qualsiasi e vi aggiunge gli interessi

conto qualsiasi e vi aggiunge gli interessi

 Se si vuol manipolare un insieme di dati presenti in Se si vuol manipolare un insieme di dati presenti in un file, si deve prestare particolare attenzione alla un file, si deve prestare particolare attenzione alla

disposizione dei dati stessi disposizione dei dati stessi

 Supposto di inserire semplicemente i dati in formato testo: Supposto di inserire semplicemente i dati in formato testo:

 Immaginiamo che il conto numero 1001 abbia un saldo Immaginiamo che il conto numero 1001 abbia un saldo

(36)

36 36

Esempio di Programma Esempio di Programma

 Vogliamo versare $100 nel conto numero Vogliamo versare $100 nel conto numero

 Se ora si scrivesse semplicemente il nuovo valore, Se ora si scrivesse semplicemente il nuovo valore, il risultato sarebbe:

il risultato sarebbe:

(37)

37 37

Esempio di Programma Esempio di Programma

 La classe La classe RandomAccessFile RandomAccessFile memorizza i memorizza i dati in binario

dati in binario

 I metodi I metodi readInt readInt e e writeInt writeInt leggono e leggono e scrivono numeri interi sotto forma di quantità di scrivono numeri interi sotto forma di quantità di

quattro byte quattro byte

 I metodi I metodi readDouble readDouble e e writeDouble writeDouble elaborano numeri in virgola mobile in doppia elaborano numeri in virgola mobile in doppia

double x = f.readDouble();

double x = f.readDouble();

f.writeDouble(x);

f.writeDouble(x);

(38)

38 38

Esempio di Programma Esempio di Programma

 Per poter aggiornare un file dovete assegnare a Per poter aggiornare un file dovete assegnare a ciascun campo una dimensione fissa che sia

ciascun campo una dimensione fissa che sia sufficientemente grande

sufficientemente grande

 Ne risulta che tutti i record (“insiemi di campi”) del file Ne risulta che tutti i record (“insiemi di campi”) del file hanno la stessa dimensione

hanno la stessa dimensione

Questo presenta il vantaggio che è molto più facile Questo presenta il vantaggio che è molto più facile

spostarsi sui record spostarsi sui record

 Quando si memorizzano numeri in un file avente Quando si memorizzano numeri in un file avente

dimensioni fisse per i record, è più facile inserirli in

dimensioni fisse per i record, è più facile inserirli in

formato binario invece che in formato testo

(39)

39 39

Esempio di Programma Esempio di Programma

 Il metodo Il metodo size size determina il numero totale di conti, determina il numero totale di conti, dividendo la lunghezza del file per la dimensione di dividendo la lunghezza del file per la dimensione di

un record un record

public int size() throws IOException public int size() throws IOException { {

return (int) (file.length() / RECORD_SIZE);

return (int) (file.length() / RECORD_SIZE);

// RECORD_SIZE è pari a 12 bytes:

// RECORD_SIZE è pari a 12 bytes:

// 4 bytes per il numero di conto e // 4 bytes per il numero di conto e // 8 bytes per il saldo

// 8 bytes per il saldo

} }

(40)

40 40

Esempio di Programma Esempio di Programma

 Per leggere dal file il conto n-esimo, il metodo read Per leggere dal file il conto n-esimo, il metodo read posiziona il puntatore del file all’indirizzo

posiziona il puntatore del file all’indirizzo n * RECORD_SIZE

n * RECORD_SIZE

(il primo conto ha indice n uguale a 0), (il primo conto ha indice n uguale a 0),

quindi legge i dati e costruisce un oggetto che quindi legge i dati e costruisce un oggetto che

rappresenta un conto bancario:

rappresenta un conto bancario:

public BankAccount read(int n) public BankAccount read(int n) throws IOException

throws IOException { {

file.seek(n * RECORD_SIZE);

file.seek(n * RECORD_SIZE);

int accountNumber = file.readInt();

int accountNumber = file.readInt();

double balance = file.readDouble();

double balance = file.readDouble();

return new BankAccount(accountNumber, balance);

return new BankAccount(accountNumber, balance);

(41)

41 41

Esempio di Programma Esempio di Programma

 Per scrivere un conto si fa, invece, così: Per scrivere un conto si fa, invece, così:

public void write(int n, BankAccount account) public void write(int n, BankAccount account) throws IOException

throws IOException { {

file.seek(n * RECORD_SIZE);

file.seek(n * RECORD_SIZE);

file.writeInt(account.getAccountNumber());

file.writeInt(account.getAccountNumber());

file.writeDouble(account.getBalance());

file.writeDouble(account.getBalance());

} }

(42)

42 42

BankDatatester.java BankDatatester.java

01: import java.io.IOException;

01: import java.io.IOException;

02: import java.io.RandomAccessFile;

02: import java.io.RandomAccessFile;

03: import java.util.Scanner;

03: import java.util.Scanner;

04: 04:

05: /**

05: /**

06: Questo programma collauda l’accesso casuale.

06: Questo programma collauda l’accesso casuale.

07: Potete accedere ai conti esistenti e aggiungervi 07: Potete accedere ai conti esistenti e aggiungervi

08: gli interessi oppure creare nuovi conti.I conti vengono 08: gli interessi oppure creare nuovi conti.I conti vengono

memorizzati in un file ad accesso casuale memorizzati in un file ad accesso casuale 09: */

09: */

10: public class

10: public class BankDataTester BankDataTester 11: {

11: {

12: public static void main(String[] args) 12: public static void main(String[] args) 13: throws IOException

13: throws IOException 14: {

14: {

15: Scanner in = new Scanner(System.in);

15: Scanner in = new Scanner(System.in);

16: BankData data = new BankData();

16: BankData data = new BankData();

17: try

17: try

(43)

43 43

BankDatatester.java BankDatatester.java

18: { 18: {

19: data.open("bank.dat");

19: data.open("bank.dat");

20: 20:

21: boolean done = false;

21: boolean done = false;

22: while (!done) 22: while (!done) 23: {

23: {

24: System.out.print("Account number: ");

24: System.out.print("Account number: ");

25: int accountNumber = in.nextInt();

25: int accountNumber = in.nextInt();

26: System.out.print("Amount to deposit: ");

26: System.out.print("Amount to deposit: ");

27: double amount = in.nextDouble();

27: double amount = in.nextDouble();

28: 28:

29: int position = data.find(accountNumber);

29: int position = data.find(accountNumber);

30: BankAccount account;

30: BankAccount account;

31: if (position >= 0) 31: if (position >= 0) 32: {

32: {

33: account = data.read(position);

33: account = data.read(position);

34: account.deposit(amount);

34: account.deposit(amount);

35: System.out.println("new balance="

35: System.out.println("new balance="

36: + account.getBalance());

36: + account.getBalance());

(44)

44 44

BankDatatester.java BankDatatester.java

38: else // Aggiungi un nuovo conto 38: else // Aggiungi un nuovo conto 39: {

39: {

40: account = new BankAccount(accountNumber, 40: account = new BankAccount(accountNumber, 41: amount);

41: amount);

42: position = data.size();

42: position = data.size();

43: System.out.println("adding new account");

43: System.out.println("adding new account");

44: } 44: }

45: data.write(position, account);

45: data.write(position, account);

46: 46:

47: System.out.print("Done? (Y/N) ");

47: System.out.print("Done? (Y/N) ");

48: String input = in.next();

48: String input = in.next();

49: if (input.equalsIgnoreCase("Y")) done = true;

49: if (input.equalsIgnoreCase("Y")) done = true;

50: } 50: } 51: }

51: }

52: finally 52: finally 53: {

53: {

54: data.close();

54: data.close();

55: }

55: }

(45)

45 45

BankData.java BankData.java

001: import java.io.IOException;

001: import java.io.IOException;

002: import java.io.RandomAccessFile;

002: import java.io.RandomAccessFile;

003:

003:

004: /**

004: /**

005: Questa classe funge da tramite per un file 005: Questa classe funge da tramite per un file

006: ad accesso casuale contenente i dati di conti bancari.

006: ad accesso casuale contenente i dati di conti bancari.

007: */

007: */

008: public class

008: public class BankData BankData 009: {

009: {

010: /**

010: /**

011: Costruisce un oggetto del tipo BankData senza 011: Costruisce un oggetto del tipo BankData senza 012: associarlo ad un file.

012: associarlo ad un file.

013: */

013: */

014: public

014: public BankData BankData() () 015: {

015: {

016: file = null;

016: file = null;

017: }

017: }

(46)

46 46

BankData.java BankData.java

018:

018:

019: /**

019: /**

020: Apre il file dei dati.

020: Apre il file dei dati.

021: @param filename il nome del file che contiene 021: @param filename il nome del file che contiene 022: informazioni sui conti bancari

022: informazioni sui conti bancari 023: */

023: */

024: public void

024: public void open open (String filename) (String filename) 025: throws IOException

025: throws IOException 026: {

026: {

027: if (file != null) file.close();

027: if (file != null) file.close();

028: file = new RandomAccessFile(filename, "rw");

028: file = new RandomAccessFile(filename, "rw");

029: } 029: } 030:

030:

031: /**

031: /**

032: Restituisce il numero di conti presenti nel file.

032: Restituisce il numero di conti presenti nel file.

033: @return il numero dei conti 033: @return il numero dei conti 034: */

034: */

035: public int

035: public int size size () ()

036: throws IOException 036: throws IOException 037: {

037: {

(47)

47 47

BankData.java BankData.java

041: /**

041: /**

042: Chiude il file dei dati.

042: Chiude il file dei dati.

043: */

043: */

044: public void

044: public void close close() ()

045: throws IOException 045: throws IOException 046: {

046: {

047: if (file != null) file.close();

047: if (file != null) file.close();

048: file = null;

048: file = null;

049: } 049: } 050:

050:

051: /**

051: /**

052: Legge il record di un nuovo conto bancario.

052: Legge il record di un nuovo conto bancario.

053: @param n l’indice del conto nel file dei dati 053: @param n l’indice del conto nel file dei dati

054: @return conto inizializzato con i dati letti dl file 054: @return conto inizializzato con i dati letti dl file 055: */

055: */

056: public BankAccount

056: public BankAccount read(int n) read (int n) 057: throws IOException

057: throws IOException 058: {

058: {

059: file.seek(n * RECORD_SIZE);

059: file.seek(n * RECORD_SIZE);

(48)

48 48

BankData.java BankData.java

064: 064:

065: /**

065: /**

066: Trova la posizione del conto bancario avente 066: Trova la posizione del conto bancario avente

// il numero di conto indicato // il numero di conto indicato

067: @param accountNumber il numero di conto da cercare 067: @param accountNumber il numero di conto da cercare 068: @return la posizione del conto trovato oppure

068: @return la posizione del conto trovato oppure 069: -1 se il non esiste conto con tale numero

069: -1 se il non esiste conto con tale numero 070: */

070: */

071: public int

071: public int find find (int accountNumber) (int accountNumber) 072: throws IOException

072: throws IOException 073: {

073: {

074: for (int i = 0; i < size(); i++) 074: for (int i = 0; i < size(); i++) 075: {

075: {

076: file.seek(i * RECORD_SIZE);

076: file.seek(i * RECORD_SIZE);

077: int a = file.readInt();

077: int a = file.readInt();

078: if (a == accountNumber) // trovato 078: if (a == accountNumber) // trovato 079: return i;

079: return i;

080: } 080: }

081: 081: return -1; // Non trovato dopo aver seaminato tutti return -1; // Non trovato dopo aver seaminato tutti

(49)

49 49

BankData.java BankData.java

083:

083:

084: /**

084: /**

085: Scrive nel file dei dati il record di un conto bancario 085: Scrive nel file dei dati il record di un conto bancario 086: @param n l’indice del conto nel file dei dati

086: @param n l’indice del conto nel file dei dati 087: @param account il conto da scrivere

087: @param account il conto da scrivere 088: */

088: */

089: public void

089: public void write write(int n, BankAccount account) (int n, BankAccount account) 090: throws IOException

090: throws IOException 091: {

091: {

092: file.seek(n * RECORD_SIZE);

092: file.seek(n * RECORD_SIZE);

093: file.writeInt(account.getAccountNumber());

093: file.writeInt(account.getAccountNumber());

094: file.writeDouble(account.getBalance());

094: file.writeDouble(account.getBalance());

095: } 095: } 096:

096:

097: private RandomAccessFile

097: private RandomAccessFile file file ; ; 098:

098:

099: public static final int INT_SIZE = 4;

099: public static final int INT_SIZE = 4;

100: public static final int DOUBLE_SIZE = 8;

100: public static final int DOUBLE_SIZE = 8;

(50)

50 50

Output Output

Account number: 1001 Account number: 1001 Amount to deposit: 100 Amount to deposit: 100 adding new account

adding new account Done? (Y/N) N

Done? (Y/N) N

Account number: 1018 Account number: 1018 Amount to deposit: 200 Amount to deposit: 200 adding new account

adding new account Done? (Y/N) N

Done? (Y/N) N

Account number: 1001 Account number: 1001 Amount to deposit: 1000 Amount to deposit: 1000 new balance=1100.0

new balance=1100.0 Done? (Y/N) Y

Done? (Y/N) Y

(51)

51 51

Flussi di Oggetti Flussi di Oggetti

 La classe La classe ObjectOutputStream ObjectOutputStream può può memorizzare sul disco interi oggetti

memorizzare sul disco interi oggetti

 La classe La classe ObjectInputStream ObjectInputStream li può li può rileggere

rileggere

 Gli oggetti vengono salvati in formato binario; Gli oggetti vengono salvati in formato binario;

di conseguenza, si usano stream e non writer

di conseguenza, si usano stream e non writer

(52)

52 52

Scrivere in un File un Oggetto di Scrivere in un File un Oggetto di

Tipo

Tipo BankAccount BankAccount

 Il flusso di uscita per oggetti memorizza Il flusso di uscita per oggetti memorizza

automaticamente nel flusso stesso tutti i campi di automaticamente nel flusso stesso tutti i campi di

esemplare dell’oggetto esemplare dell’oggetto

BankAccount b = . . .;

BankAccount b = . . .;

ObjectOutputStream out = new ObjectOutputStream(

ObjectOutputStream out = new ObjectOutputStream(

new FileOutputStream("bank.dat"));

new FileOutputStream("bank.dat"));

out.writeObject(b);

out.writeObject(b);

(53)

53 53

Scrivere in un File un Oggetto di Scrivere in un File un Oggetto di

Tipo

Tipo BankAccount BankAccount

 Si usa il metodo Si usa il metodo readObject readObject della classe della classe ObjectInputStream

ObjectInputStream , che restituisce un , che restituisce un riferimento di tipo

riferimento di tipo Object Object

 Dovrete ricordare i tipi degli oggetti che avete Dovrete ricordare i tipi degli oggetti che avete memorizzato e usare un cast

memorizzato e usare un cast

ObjectInputStream in = new ObjectInputStream in = new

ObjectInputStream(new FileInputStream("bank.dat"));

ObjectInputStream(new FileInputStream("bank.dat"));

BankAccount b = (BankAccount) in.readObject();

BankAccount b = (BankAccount) in.readObject();

(54)

54 54

Scrivere in un File un Oggetto di Scrivere in un File un Oggetto di

Tipo

Tipo BankAccount BankAccount

 Il metodo Il metodo readObject readObject può lanciare un’eccezione può lanciare un’eccezione di tipo

di tipo ClassNotFoundException ClassNotFoundException

 È un’eccezione controllata È un’eccezione controllata

 La si cattura oppure la si dichiara in una clausola La si cattura oppure la si dichiara in una clausola throws

throws

(55)

55 55

 Con una sola istruzione si può salvare il vettore e Con una sola istruzione si può salvare il vettore e tutti gli oggetti cui fa riferimento

tutti gli oggetti cui fa riferimento

 E con una sola istruzione si possono rileggere tutti E con una sola istruzione si possono rileggere tutti

ArrayList<BankAccount> a = new ArrayList<BankAccount>();

ArrayList<BankAccount> a = new ArrayList<BankAccount>();

// Ora inserisci in a molti oggetti di tipo BankAccount // Ora inserisci in a molti oggetti di tipo BankAccount out.writeObject(a);

out.writeObject(a);

ArrayList<BankAccount> a = ArrayList<BankAccount> a =

(ArrayList<BankAccount>) in.readObject(); (ArrayList<BankAccount>) in.readObject();

Scrivere e Leggere un Scrivere e Leggere un

ArrayList

ArrayList

(56)

56 56

Interfaccia

Interfaccia Serializable Serializable

 In un flusso di oggetti possono essere memorizzati In un flusso di oggetti possono essere memorizzati soltanto esemplari di classi che realizzino

soltanto esemplari di classi che realizzino l’interfaccia

l’interfaccia Serializable Serializable

 Questa interfaccia non ha metodi Questa interfaccia non ha metodi

class BankAccount implements Serializable class BankAccount implements Serializable { {

. . .

. . .

} }

(57)

57 57

Interfaccia

Interfaccia Serializable Serializable

 Il processo di memorizzazione degli oggetti in un Il processo di memorizzazione degli oggetti in un flusso viene chiamato

flusso viene chiamato serializzazione serializzazione

 Ad ogni oggetto viene assegnato un Ad ogni oggetto viene assegnato un numero di serie numero di serie all’interno del flusso

all’interno del flusso

 Se lo stesso oggetto viene salvato due volte, la Se lo stesso oggetto viene salvato due volte, la

seconda volta viene scritto soltanto il suo numero di seconda volta viene scritto soltanto il suo numero di

serie serie

 Quando gli oggetti vengono poi riletti, i numeri di Quando gli oggetti vengono poi riletti, i numeri di

serie ripetuti sono considerati come riferimenti allo

serie ripetuti sono considerati come riferimenti allo

(58)

58 58

SerialTester.java SerialTester.java

01: import java.io.File;

01: import java.io.File;

02: import java.io.IOException;

02: import java.io.IOException;

03: import java.io.FileInputStream;

03: import java.io.FileInputStream;

04: import java.io.FileOutputStream;

04: import java.io.FileOutputStream;

05: import java.io.ObjectInputStream;

05: import java.io.ObjectInputStream;

06: import java.io.ObjectOutputStream;

06: import java.io.ObjectOutputStream;

07: 07:

08: /**

08: /**

09: Questo programma verifica la serializzazione di un oggetto 09: Questo programma verifica la serializzazione di un oggetto 10: di tipo Bank. Se esiste un file con i dati serializzati di 10: di tipo Bank. Se esiste un file con i dati serializzati di 11: una banca,esso viene caricato;altrimenti il programma parte 11: una banca,esso viene caricato;altrimenti il programma parte 12: con una nuova banca. Ulteriori conti bancari sono aggiunti 12: con una nuova banca. Ulteriori conti bancari sono aggiunti 13: alla banca, quindi i dati della banca vengono memorizzati 13: alla banca, quindi i dati della banca vengono memorizzati

nel file nel file 14: */

14: */

15: public class

15: public class SerialTester SerialTester 16: {

16: {

(59)

59 59

SerialTester.java SerialTester.java

17: public static void

17: public static void main main(String[] args) (String[] args)

18: throws IOException, ClassNotFoundException 18: throws IOException, ClassNotFoundException 19: {

19: {

20: Bank firstBankOfJava;

20: Bank firstBankOfJava;

21:

21:

22: File f = new File("bank.dat");

22: File f = new File("bank.dat");

23: if (f.exists()) 23: if (f.exists()) 24: {

24: {

25: ObjectInputStream in = new ObjectInputStream 25: ObjectInputStream in = new ObjectInputStream 26: (new FileInputStream(f));

26: (new FileInputStream(f));

27: firstBankOfJava = (Bank) in.readObject();

27: firstBankOfJava = (Bank) in.readObject();

28: in.close();

28: in.close();

29: } 29: }

30: else 30: else 31: {

31: {

32: firstBankOfJava = new Bank();

32: firstBankOfJava = new Bank();

33: firstBankOfJava.addAccount(new 33: firstBankOfJava.addAccount(new BankAccount(1001, 20000));

BankAccount(1001, 20000));

(60)

60 60

SerialTester.java SerialTester.java

34: firstBankOfJava.addAccount(new 34: firstBankOfJava.addAccount(new

BankAccount(1015, 10000)); BankAccount(1015, 10000));

35: } 35: } 36: 36:

37: // Effettua alcuni versamenti 37: // Effettua alcuni versamenti

38: BankAccount a = firstBankOfJava.find(1001);

38: BankAccount a = firstBankOfJava.find(1001);

39: a.deposit(100);

39: a.deposit(100);

40: System.out.println(a.getAccountNumber() 40: System.out.println(a.getAccountNumber()

+ ":" + a.getBalance()); + ":" + a.getBalance());

41: a = firstBankOfJava.find(1015);

41: a = firstBankOfJava.find(1015);

42: System.out.println(a.getAccountNumber() 42: System.out.println(a.getAccountNumber()

+ ":" + a.getBalance()); + ":" + a.getBalance());

43: 43:

44: ObjectOutputStream out = new ObjectOutputStream 44: ObjectOutputStream out = new ObjectOutputStream 45: (new FileOutputStream(f));

45: (new FileOutputStream(f));

46: out.writeObject(firstBankOfJava);

46: out.writeObject(firstBankOfJava);

47: out.close();

47: out.close();

48: }

48: }

49: }

49: }

(61)

61 61

Output Output

1001:20100.0 1001:20100.0 1015:10000.0 1015:10000.0

1001:20200.0 1001:20200.0 1015:10000.0 1015:10000.0

 Prima esecuzione del programma Prima esecuzione del programma

 Seconda esecuzione del programma Seconda esecuzione del programma

Riferimenti

Documenti correlati

Costruire un file Excel che risolva il seguente problema e che funzioni cambiando OGNI importo, o tempo o tasso di attualizzazione (importi riquadrati e

A two-parameter family of Harnack type inequalities for non-negative solutions of a class of singular, quasilinear, homogeneous parabolic equations is established, and it is shown

Cruise STR06 on R/V Urania was performed in the framework of the ”INGV - DPC V2 - Mon- itoring and research activity at Stromboli and Panarea - Unit V2/03”, and resulted as a

In order t o characterize the critical behavior of the DSSki systems, we define the minimum interarrival time E,, for each earth station as that particular mean

ARCHIVIO.C Il secondo programma deve gestire un archivio di persone che vengono memorizzate in un file INI diviso in due sezioni: nella prima sezione, “Struttura” , c’è un

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

La prova si sosterrà nella data dell’appello e si accederà alla successiva prova orale con una valutazione di almeno 18/30.. Il risultato della prova scritta sarà

I seguenti studenti hanno raggiunto i 2/3 delle ore di frequenza richiesta, pertanto possono iscriversi agli appelli del corso... Elenco studenti che possono sostenere l’esame