Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo...

26
Input-Output 16 Maggio 2006

Transcript of Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo...

Page 1: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Input-Output

16 Maggio 2006

Page 2: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Nei programmi sviluppati sino ad oggi abbiamo usato 

* output su schermo (con System.out.print e System.out.print)

* input da tastiera (con la classe Input)

Se un programma deve leggere o scrivere grandi quantità di dati, è conveniente memorizzare questi dati in files. 

Java fornisce classi e metodi per scrivere e leggere dati da files

(nel package java.io)

Page 3: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

I dati possono essere memorizzati in un file in formato

•testo (sequenza di caratteri, leggibile da esseri umani)

•binario (sequenza di byte)

•Vedremo solo il primo caso (il secondo comunque e’ piu’ efficiente)

•Per esempio formato testo per il numero intero 12354,

`1` `2``3``5``4` un carattere alla volta

Page 4: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Ricordiamo che

• Tipo Primitivo: char

• Contiene un solo carattere tra apici singoli

‘a’ carattere

“a” stringa

Il metodo charAt (int i) permette di leggere il carattere in posizione i di una stringa

Page 5: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Classi per I/O su files

Input da file Output su file

Formato testo FileReader FileWriter

Formato binario FileInputStream FileOutputStream

Queste classi gestiscono I/O di caratteri o bytes da files: per dati più complessi (stringhe, numeri) introdurremo altre classi. I file di testo possono essere aperti, esaminati e modificati usando normali editor (es. emacs).

Page 6: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Lettura di singoli caratteri da file

Per leggere dati (un carattere alla volta) da un file, occorre:

* ricordarsi di importare il pacchetto java.io; 

import java.io.*;

•creare un oggetto della classe FileReader, passando il nome del file al costruttore; 

    FileReader filein = new FileReader("dati.txt"); 

Page 7: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Per leggere

• utilizzare il metodo  public int read() della classe FileReader per leggere i caratteri;

    int next = filein.read();

• Il metodo read() restituisce un intero che può essere:

• -1 se si è arrivati alla fine del file;

• un intero che rappresenta il codice di un carattere UNICODE.

• Tipicamente, si controlla se il numero letto è diverso da -1 e in questo caso si trasforma l'intero in un char usando l'operatore di cast.

char c = (char) next;

Page 8: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Attenzione

•I metodi e il costruttore di FileReader possono lanciare una eccezione di tipo IOException  che rappresenta un errore di I/O. Queste eccezioni sono controllate, e quindi devono essere previste dal programmatore.

•Quando si termina di leggere o scriverebisogna “chiudere” il file con il metodo public void close().

    filein.close();

Page 9: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Esempio di lettura da file

•CopyRead.java: stampa su video del contenuto di un file (copyread.txt). Le eventuali IOException non vengono gestite dal programma ma rinviate al chiamante.

•Importante: Cosa succede se non dichiariamo che main può lanciare IOException?

•Le eccezioni controllate devono essere riportate nell’intestazione del metodo tramite throws?

 

Page 10: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

import java.io.*;

public class CopyRead {    public static void main(String [] args) throws IOException {         // apre il file in lettura        FileReader filein = new FileReader("copyread.txt"); 

        int next;        char nextc;        do {            next = filein.read();  // legge il prossimo carattere

            if (next != -1) {  // se non e' finito il file                nextc = (char) next;                 System.out.print(nextc);  // stampa il carattere            }

        } while (next != -1);

        filein.close();  //chiude il file        System.out.println();    }}

Page 11: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Scrittura di caratteri su file

Per scrivere dati su di un file, occorre:

•creare un oggetto della classe FileWriter, passando il nome del file al costruttore; 

*utilizzare il metodo public void write(int c) per scrivere i caratteri;

*chiudere il file con il metodo close().

Anche questi metodi possono lanciare una IOException.

 

Page 12: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

CopyWrite.java: scrive in un file (copywrite.txt) una stringa fornita dall'utente, un carattere alla volta.

import java.io.*;

public class CopyWrite {    public static void main(String[] args) throws IOException {

        // apre il file copywrite.txt in scrittura         FileWriter fileout = new FileWriter("copywrite.txt");

        System.out.print("Scrivi una stringa: ");

        // legge una stringa da tastiera         String str = Input.readLine();

        // un ciclo scrive ogni carattere delle stringa nel file         for (int i = 0; i < str.length(); i++)            fileout.write(str.charAt(i));

        fileout.close();  // chiude il file    }}

Page 13: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Le classi FileReader e FileWriter forniscono i metodi basici per leggere o scrivere caratteri su file. Non è conveniente usarle direttamente nei programmi perché:

•rendono un programma inefficiente, visto che ogni operazione di I/O (read o write di singolo carattere) richiede un accesso al file;

•non permettono di leggere/scrivere direttamente dati più complessi come stringhe e numeri.

Altre classi di Java forniscono funzionalità di I/O più avanzate, ne vedremo alcune

Page 14: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Altre classi di Java forniscono funzionalità di I/O più avanzate, in particolare

•BufferedReader e BufferedWriter usano un buffer (memoria tampone) per memorizzare temporaneamente i caratteri da leggere/scrivere, in modo da ridurre il numero di accessi al file;

•PrintWriter fornisce i metodi print e println, che permettono di scrivere qualunque dato Java, convertendolo automaticamente in stringa.

Gli oggetti di queste classi sono dei wrappers: incapsulano gli oggetti delle classi FileReader e FileWriter estendendone le funzionalità.

Page 15: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Esempio

• Vogliamo scrivere direttamente in un file un numero, un oggetto (il suo stato interno), o una stringa

FileWriter fileout = new FileWriter("copyprintwrite.txt");

        // ... che incapsulo in un PrintWriter

  PrintWriter printout = new PrintWriter(fileout);

Page 16: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

PrintWriter

• Ha metodi print e println per stampare numeri oggetti e stringhe

• Allo stesso tempo questi metodi convertono tutto in una stringa, la stringa viene poi scomposta in caratteri e mandata all’oggetto

FileWriter corrispondente

Page 17: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

FileWriter fileout = new FileWriter("copyprintwrite.txt");

        // ... che incapsulo in un PrintWriter

PrintWriter printout = new PrintWriter(fileout);

printout.println(115); //numero

printout.println(“Hello”); //Una stringa

printout.println(new Studente(“pippo”); //Un oggetto

•Nel caso dell’oggetto viene usato ToString(),

alla fine nel file e’ memorizzata la Stringa un

carattere alla volta

Page 18: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

•Conviene usare la classe BufferedReader fornisce il metodo readLine() che legge una riga (String)

•In pratica continua a leggere nel file di input dell’oggetto lettore relativo tramite read() fino a costruire una stringa•Quando i dati sono terminati readLine() restituisce null

•non ha metodi per leggere, ad esempio, interi o double. 

Lettura di dati da file

Page 19: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

import java.io.*;

public class CopyBufferedRead {    public static void main(String [] args) throws IOException {

        // incapsula in BufferedReader un file aperto in lettura         BufferedReader filebuf =              new BufferedReader(new FileReader("copyread.txt"));                 String nextStr;

// legge una riga del file         nextStr = filebuf.readLine();              while (nextStr != null){            System.out.println(nextStr);  // visualizza la riga             nextStr = filebuf.readLine(); // legge la prossima riga         }         filebuf.close();  // chiude il file     }}

•La differenza rispetto al programma visto prima e’ che legge stringhe,non caratteri

Page 20: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Primo esercizio

• Scrivere programma che copia il file "inp.txt" nel file "out.txt” un carattere alla volta

• Modificarlo in modo che legga una linea alla volta

Page 21: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Una soluzioneimport java.io.*;

public class CopiaFile { public static void main(String [] args) throws IOException {

// apre il file in lettura

FileReader filein=new FileReader("inp.txt");FileWriter fileout = new FileWriter("out.txt");

int next;char nextc;do { next = filein.read(); // legge il prossimo carattere

if (next != -1) { // se non e' finito il filenextc = (char) next; System.out.print(nextc); // stampa il carattere

fileout.write(nextc); }

} while (next != -1); filein.close();

fileout.close(); //chiude il fileSystem.out.println();}}

Page 22: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Secondo Esercizio

• Dato un file integers.txt che contiene una sequenza di interi uno per linea

• Scrivere un programma che calcola la somma degli interi contenuti nel file

• Si può convertire una stringa in un numero usando i metodi statici Integer.parseInt e Double.parseDouble.

Page 23: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

public class SommaInteri { public static void main(String[] args){

String inputFileName = "./integers.txt"; String line = null;

try { BufferedReader in = new BufferedReader(new FileReader(inputFileName)); line = in.readLine(); int somma =0; while(line!=null){

// se non e' possibile convertire la stringa line in intero// viene lanciata un'eccezione NumberFormatException// (catturata sotto con catch apposito)int numero = Integer.parseInt(line);

somma += numero;line = in.readLine();

} in.close(); System.out.println(" la somma e' "+ somma); } catch(FileNotFoundException e) { System.out.println(inputFileName+" FileNotFound");} catch(NumberFormatException e) { System.out.println(" linea non corretta: --> "+line+" <--");

} catch(IOException e) { System.out.println(" IOException "+e);

}}}

Page 24: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Eccezioni

• Si possono verificare varie eccezioni• FileNotFoundException se non si trova il

file

• NumberFormaxception se la stringa letta nel file non si puo’ convertire in intero

Page 25: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Quindi

• Sarebbe meglio gestire le eccezioni invece che propagarle

• Modificare il programma SommaInteri in modo che quando si verifica un'eccezione venga comunque stampata la somma calcolata fino a quel momento.

• 2. Modificare il programma [SommaInteri] in modo che quando si verifica un'eccezione di tipo NumberFormatException dovuta ad una linea del file non convertibile in intero si scarti tale riga ma si prosegua con il calcolo della somma.

Page 26: Input-Output 16 Maggio 2006. Nei programmi sviluppati sino ad oggi abbiamo usato * output su schermo (con System.out.print e System.out.print ) * input.

Esercizio Aggiuntivo

Scrivere un programma CatFiles contenente il metodo statico public static void concat(String [] inFiles, String outFile)

che concatena il contenuto dei files il cui nome è nell'array inFiles nel file il cui nome è outFile.

Se una delle stringhe dell'array inFiles non corrisponde ad un file reale, la stringa viene ignorata e si passa alla prossima. Eventuali altre eccezioni di I/O devono essere catturate dal metodo, che in questo caso deve lanciare una IllegalArgumentException.

Per testare il programma, scrivere una semplice classe TestCatFiles che nel main invoca il metodo in questione dopo aver chiesto i nomi dei file all'utente. Controllare che l'effetto sia quello desiderato.