Flussi, lettori e scrittori
Per sequenze di byte, InputStream,
OutputStream e loro sottoclassi.
„
Es:
InputStream in = …;
int next = in. read();
if (next != -1)
byte b = (byte) next;
Per sequenze di caratteri, Reader, Writer e
loro sottoclassi
„
Es:
Reader reader = …;
int next = reader. read();
if (next != -1)
char c = (char) next;
Operazioni di I/O con i File
Leggere e scrivere sequenze di byte da file
su disco: FileInputStream e FileOutputStream
„
FileInputStream in = new
FileInputStream(“input.dat”);
Leggere dati di testo da un file su disco:
FileReader e FileWriter
„
FileReader reader = new FileReader (“input.txt”);
File di Testo
La classe BufferedReader con readline()
„
FileReader reader = new FileReader(“inp.txt”);
BufferedReader in = new BufferedReader(reader);
String inputLine = in.readLine();
double x = Double.parseDouble(inputLine);
La classe PrintWriter
„
print e println
Alla fine:
„
reader.close()
o, per un oggetto writer della classe PrintWriter,
writer.close()
La gerarchia
delle eccezioni
• Eccezioni controllate
• Eccezioni non controllate
Esempio: una classe di prodotti
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
public class Product
{ public Product() {...}
public Product(String aName, double aPrice, int aScore) {...}
public boolean read(BufferedReader in) throws IOException {...}
public String getName() {...}
public double getPrice() {...}
public int getScore() {...}
public void setPrice(double newPrice) {...}
private String name;
private double price;
private int score;
}
Esempio:
leggere prodotti da un file di testo
public boolean read (BufferedReader in) throws IOException
{ name = in.readLine(); // legge il nome del prodotto
if (name == null) return false;
String inputLine = in.readLine(); // legge il prezzo del prodotto
if (inputLine == null)
throw new EOFException ("EOF durante la lettura del prezzo");
price = Double.parseDouble(inputLine);
// legge il punteggio del prodotto
inputLine = in.readLine();
if (inputLine == null)
throw new EOFException ("EOF durante la lettura del
punteggio");
score = Integer.parseInt(inputLine);
return true; }
Esempio prodotti: gestire le eccezioni
public void openFile()
{
BufferedReader in = null;
try
{…
// mostra la finestra di dialogo di scelta del file
in = new BufferedReader (new FileReader(selectedFile));
readProducts(in);
}
catch(FileNotFoundException e)
{
JOptionPane.showMessageDialog
(null, "Nome del file errato. Prova di nuovo."); }
catch(IOException e)
{
JOptionPane.showMessageDialog
(null, "File alterato. Prova di nuovo.");}
finally
{
if (in != null)
try { in.close(); }
catch(IOException e)
{
JOptionPane.showMessageDialog
(null, "Errore nella chiusura del file.");} }
}
Esempio prodotti: gestire le eccezioni
public void readProducts(BufferedReader in) throws IOException
{
boolean done = false;
while (!done)
{
Product p = new Product();
if (p.read(in))
panel.addProduct(p);
else // ha letto ultimo prodotto
done = true;
}
}
Accesso sequenziale e accesso casuale
Accesso sequenziale
Record a dimensione variabile
e a dimensione fissa
Programma Database.java
import java.io.IOException;
import java.io.RandomAccessFile;
public class Database
{ public static void main(String[] args)
{ ConsoleReader console = new ConsoleReader(System.in);
System.out.println
(“Inserire il nome del file di dati:");
String filename = console.readLine();
try
{ RandomAccessFile file
= new RandomAccessFile(filename, "rw");
long nrecord = file.length() / RECORD_SIZE;
boolean done = false;
while (!done)
{ System.out.println
(“Indicare il record da aggiornare (1 - "
+ nrecord + "), nuovo record (0), uscire (-1)");
int pos = console.readInt();
if (1 <= pos && pos <= nrecord) // aggiorna il record
{ file.seek((pos - 1) * RECORD_SIZE);
Product p = readProduct(file);
System.out.println(“Trovato ” + p.getName()
+ ” ” + p.getPrice() + ” ” + p.getScore());
System.out.println
(“Immettere il nuovo prezzo:");
double newPrice = console.readDouble();
p.setPrice(newPrice);
file.seek((pos - 1) * RECORD_SIZE);
writeProduct(file, p);
}
else if (pos == 0) // aggiunge un record
{ System.out.println(“Immettere il nuovo prodotto:");
String name = console.readLine();
System.out.println(“Immettere il prezzo:");
double price = console.readDouble();
System.out.println(“Immettere il punteggio:");
int score = console.readInt();
Product p = new Product(name, price, score);
file.seek(nrecord * RECORD_SIZE);
writeProduct(file, p);
nrecord++;
}
else if (pos == -1)
done = true;
}
file.close();
}
catch(IOException e)
{ System.out.println(“Eccezione Input/Output ” + e);
}
}
/**
Legge una stringa di lunghezza fissa.
@param f il file dal quale leggere
@param size il numero di caratteri da leggere
@return la stringa alla quale sono stati tolti gli spazi eccedenti
*/
public static String readFixedString(RandomAccessFile f,
int size) throws IOException
{ String b = “";
for (int i = 0; i < size; i++)
b += f.readChar();
return b.trim();
}
/**
Scrive una stringa di lunghezza fissa.
@param f il file sul quale scrivere
@param size il numero di caratteri da scrivere
*/
public static void writeFixedString(RandomAccessFile f,
String s, int size) throws IOException
{ if (s.length() <= size)
{ f.writeChars(s);
for (int i = s.length(); i < size; i++)
f.writeChar(’ ');
}
else
f.writeChars(s.substring(0, size));
}
/**
Legge un record di un prodotto.
@param f il file dal quale leggere
@return il prodotto successivo memorizzato nel file.
*/
public static Product readProduct(RandomAccessFile
{
f)
throws IOException
String name = readFixedString(f, NAME_SIZE);
double price = f.readDouble();
int score = f.readInt();
return new Product(name, price, score);
}
/**
Scrive un record di un prodotto.
@param f il file sul quale scrivere
*/
public static void writeProduct(RandomAccessFile f,
Product p) throws IOException
{ writeFixedString(f, p.getName(), NAME_SIZE);
f.writeDouble(p.getPrice());
f.writeInt(p.getScore());
}
public static final int NAME_SIZE = 30;
public static final int CHAR_SIZE = 2;
public static final int INT_SIZE = 4;
public static final int DOUBLE_SIZE = 8;
public static final int RECORD_SIZE
= CHAR_SIZE * NAME_SIZE + DOUBLE_SIZE + INT_SIZE;
}
File di database relazionali
Flussi di Oggetti
Per scrivere e leggere oggetti possiamo
scomporli nelle loro parti elementari e
scrivere e leggere queste parti, ma...
In Java c’è una soluzione più semplice:
le classi ObjectOutputStream e
ObjectInputStream
In un solo colpo scriviamo o leggiamo
interi oggetti!
L’Interfaccia Serializable
public class Razionale implements Serializable, ...
{ ... }
....
Razionale r = new Razionale(3,5);
ObjectOutputStream out =
new ObjectOutputStream (new FileOutputStream(“dati.dat”));
out.writeObject (r);
o, ancora meglio...
Possiamo scrivere (o leggere) in un solo colpo
intere collezioni di oggetti:
Vector v = new Vector();
String s = Console.readString();
Razionale r = Razionale.parseRaz(s);
v.add(r);
ObjectOutputStream out =
new ObjectOutputStream (new FileOutputStream(“dati.dat”));
out.writeObject (v);