I File in Java: differenze tra le versioni
(→Lettura e scrittura bufferizzata) |
(→Classe RandomAccessFile) |
||
(Una versione intermedia di uno stesso utente non sono mostrate ) | |||
Riga 305: | Riga 305: | ||
bufferReader.close(); | bufferReader.close(); | ||
fileInput.close(); | fileInput.close(); | ||
+ | |||
+ | } catch (IOException e) { | ||
+ | // TODO Auto-generated catch block | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == File ad accesso casuale == | ||
+ | La classe RandomAccessFile permette di accedere in lettura e scrittura a file ad accesso casuale, ovvero permette di muoversi all'interno del file in qualunque posizione si desideri in maniera non sequenziale. | ||
+ | |||
+ | Di seguito si trova un esempio che mostra come è possibile utilizzare questa classe. | ||
+ | <syntaxhighlight lang="java" line> | ||
+ | import java.io.IOException; | ||
+ | import java.io.RandomAccessFile; | ||
+ | |||
+ | public class Principale6 { | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | new Principale6().run(); | ||
+ | } | ||
+ | |||
+ | public void run() { | ||
+ | /* La classe RandomAccessFile permette di istanziare oggetti | ||
+ | * in grado di gestire l'accesso casuale ai file. | ||
+ | * Un oggetto di tipo RandomAccessFile può essere istanziato specificando il percorso del file (o in oggetto di tipo File) | ||
+ | * e la modalità di apertura. | ||
+ | * In questo contesto, le principali modalità di apertura dei file sono: | ||
+ | * - r: apertura in sola modalità lettura; | ||
+ | * - rw: apertura in modalità lettura e scrittura. In questo caso, se il file non esiste, esso viene creato. | ||
+ | */ | ||
+ | |||
+ | RandomAccessFile raf; | ||
+ | int i, num; | ||
+ | try { | ||
+ | // Scrittura su file binario di numeri acquisiti da tastiera | ||
+ | raf = new RandomAccessFile("datiRandom.dat", "rw"); | ||
+ | int[] v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | ||
+ | |||
+ | for (i = 0; i < 10; i++) { | ||
+ | // writeInt scrive un numero intero sul file | ||
+ | raf.writeInt(v[i]); | ||
+ | } | ||
+ | |||
+ | raf.close(); | ||
+ | |||
+ | raf = new RandomAccessFile("datiRandom.dat", "r"); | ||
+ | System.out.println("Il file è grande: " + raf.length() + "bytes"); | ||
+ | int first, last; | ||
+ | |||
+ | // readInt legge un numero intero dal file | ||
+ | first = raf.readInt(); | ||
+ | |||
+ | // seek permette di muoversi all'interno del file | ||
+ | raf.seek(raf.length() - 4); | ||
+ | |||
+ | |||
+ | last = raf.readInt(); | ||
+ | raf.close(); | ||
+ | |||
+ | System.out.println("Il primo numero vale: " + first); | ||
+ | System.out.println("L'ultimo numero vale: " + last); | ||
} catch (IOException e) { | } catch (IOException e) { |
Versione attuale delle 15:14, 5 mag 2018
Vitoantonio Bevilacqua vitoantonio.bevilacqua@poliba.it
Antonio Brunetti antonio.brunetti@poliba.it
Gianpaolo Francesco Trotta gianpaolofrancesco.trotta@poliba.it
Pagina in lavorazione
Indice
Introduzione
Java fornisce classi e metodi per scrivere e leggere dati da files; le tipologie di files che si possono trovare sono sostanzialmente due:
- file di testo;
- file binari.
Grazie alle classi fornite da Java, la gestione dell'input/output da file è indipendente dalla piattaforma su cui il programma verrà eseguito; inoltre, le operazioni di I/O sono basate sul concetto di flusso (stream), ovvero una sequenza ordinata di dati che ha una sorgente e una destinazione.
Per leggere dati da una sorgente bisogna collegarla a uno stream, dove leggere le informazioni in modo ordinato. Analogamente, per scrivere dati su una destinazione, bisogna collegarla a uno stream in cui inserire i dati in modo sequenziale. All’inizio di queste operazioni occorre aprire lo stream e alla fine occorre chiuderlo.
Lettura e scrittura di caratteri con file di testo
Introduzione alle classi e ai metodi per la lettura e scrittura di caratteri o byte su file.
Di seguito sono riportati due esempi che implementano I/O con i file.
Lettura da file di testo
import java.io.*;
public class Principale {
public static void main(String[] args) {
new Principale().run();
}
public void run() {
/* Per la lettura e scrittura di file,
* si utilizzano le classi di java.io:
* - FileReader (FileInputStream)
* - FileWriter (FileOutputStream)
* che permettono di gestire l'I/O di caratteri o bytes
*/
FileReader file;
try {
// Lettura di file di testo con due letture successive
file = new FileReader("dati.txt");
int carattere = file.read();
int carattere2 = file.read();
System.out.println("Il codice del carattere vale: " + carattere);
System.out.println("Il codice del carattere vale: " + carattere2);
file.close();
// Lettura di tutto il contenuto del file di testo con ciclo while
file = new FileReader("dati.txt");
// Letura di tutti i caratteri all'interno di un file di testo
int next = file.read();
while(next != -1) {
char nextc = (char) next;
System.out.print(nextc); // stampa il carattere
next = file.read(); // legge il prossimo carattere
}
file.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Scrittura su file di testo
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class Principale2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Principale2().run();
}
public void run() {
/* Per la lettura e scrittura di file,
* si utilizzano le classi di java.io:
* - FileReader (FileInputStream)
* - FileWriter (FileOutputStream)
* che permettono di gestire l'I/O di caratteri o bytes
*/
FileWriter file;
Scanner s = new Scanner(System.in);
try {
// Scrittura su file di testo di numeri acquisiti da tastiera
file = new FileWriter("dati_output.txt");
String num = s.nextLine();
while(!num.equals("-1")) {
file.write(num + " ");
num = s.nextLine();
}
file.close();
System.out.println("Dati scritti e file chiuso");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Scrittura e lettura con file binari
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Principale3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Principale3().run();
}
public void run() {
/* Per la lettura e scrittura di file,
* si utilizzano le classi di java.io:
* - FileReader (FileInputStream)
* - FileWriter (FileOutputStream)
* che permettono di gestire l'I/O di caratteri o bytes
*/
FileOutputStream fileOutput;
Scanner s = new Scanner(System.in);
try {
// Scrittura su file binario di numeri acquisiti da tastiera
fileOutput = new FileOutputStream("dati_output.dat");
int num = s.nextInt();
while(num != -1) {
fileOutput.write(num);
num = s.nextInt();
}
fileOutput.close();
System.out.println("Dati scritti e file chiuso");
FileInputStream fileInput;
fileInput = new FileInputStream("dati_output.dat");
int numR = fileInput.read();
while (numR != -1) {
System.out.println("Il numero letto vale: " + numR);
numR = fileInput.read();
}
fileInput.close();
System.out.println("Raggiunta fine del file");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Lettura e scrittura bufferizzata
Per la gestione dell'input/output con i file, è possibile utilizzare metodi di classi che implementano funzionalità di I/O più avanzate. Nello specifico, qui verranno utilizzate le classi BufferedReader e BufferedWriter che, a differenza delle classi precedenti (FileReader e FileWriter), riducono il numero di accessi a file e consentono di scrivere/leggere dati più complessi dei singoli bytes utilizzando dei buffer per memorizzare temporaneamente i dati da scrivere.
Di seguito ci sono 2 esempi che implementano la lettura e la scrittura bufferizzata sui file di testo.
Scrittura bufferizzata su file di testo
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class Principale4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Principale4().run();
}
public void run() {
/* Le classi FileReader e FileWriter forniscono i metodi di base
* per leggere o scrivere caratteri su file.
* Non è conveniente usarle direttamente nei programmi perché
* non permettono di leggere/scrivere direttamente
* dati più complessi come stringhe e numeri.
*/
/* Per ovviare a questo problema di possono utilizzare classi che
* implementano funzionalità di I/O più avanzate.
* - BufferedReader
* - BufferedWriter
* usano un buffer 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.
*/
// Scrittura di dati su file
FileWriter fileOutput;
BufferedWriter bufferWriter;
PrintWriter printWriter;
Scanner s = new Scanner(System.in);
try {
// Scrittura su file testo di numeri acquisiti da tastiera
fileOutput = new FileWriter("dati_output2.txt");
bufferWriter = new BufferedWriter(fileOutput);
printWriter = new PrintWriter(bufferWriter);
int num = s.nextInt();
while(num != -1) {
printWriter.println(num);
num = s.nextInt();
}
System.out.println("Dati scritti");
// Proviamo con un vettore
int[] v = {1, 2, 3, 4, 5};
// L'istruzione seguente non stampa gli elementi del vettore, ma solo il valore utilizzato come reference
printWriter.print(v);
/* Il seguente ciclo for permette la stampa su file di testo degli elementi contenuti nel vettore
* for (int i = 0; i < 5; i++) {
* printWriter.print(v[i] + " ");
* }
*/
System.out.println("Vettore scritto");
printWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Lettura bufferizzata da file di testo
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Principale5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Principale5().run();
}
public void run() {
/* Le classi FileReader e FileWriter forniscono i metodi basici
* per leggere o scrivere caratteri su file.
* Non è conveniente usarle direttamente nei programmi perché
* non permettono di leggere/scrivere direttamente
* dati più complessi come stringhe e numeri.
*/
/* Per ovviare a questo problema di possono utilizzare classi che
* implementano funzionalità di I/O più avanzate.
* - BufferedReader
* - BufferedWriter
* usano un buffer 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.
*/
// Scrittura di dati da file
FileReader fileInput;
BufferedReader bufferReader;
int i, num;
try {
// Lettura da file di testo di numeri
fileInput = new FileReader("dati_output2.txt");
bufferReader = new BufferedReader(fileInput);
String s = bufferReader.readLine();
while (s != null) {
System.out.println(s);
s = bufferReader.readLine();
}
for (i = 0; i < 10; i++) {
// L'istruzione seguente permette di convertire in intero una stringa...
// funzioni analoghe esistono per gli altri tipi di valori
num = Integer.parseInt(bufferReader.readLine());
System.out.println(num);
}
bufferReader.close();
fileInput.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
File ad accesso casuale
La classe RandomAccessFile permette di accedere in lettura e scrittura a file ad accesso casuale, ovvero permette di muoversi all'interno del file in qualunque posizione si desideri in maniera non sequenziale.
Di seguito si trova un esempio che mostra come è possibile utilizzare questa classe.
import java.io.IOException;
import java.io.RandomAccessFile;
public class Principale6 {
public static void main(String[] args) {
new Principale6().run();
}
public void run() {
/* La classe RandomAccessFile permette di istanziare oggetti
* in grado di gestire l'accesso casuale ai file.
* Un oggetto di tipo RandomAccessFile può essere istanziato specificando il percorso del file (o in oggetto di tipo File)
* e la modalità di apertura.
* In questo contesto, le principali modalità di apertura dei file sono:
* - r: apertura in sola modalità lettura;
* - rw: apertura in modalità lettura e scrittura. In questo caso, se il file non esiste, esso viene creato.
*/
RandomAccessFile raf;
int i, num;
try {
// Scrittura su file binario di numeri acquisiti da tastiera
raf = new RandomAccessFile("datiRandom.dat", "rw");
int[] v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (i = 0; i < 10; i++) {
// writeInt scrive un numero intero sul file
raf.writeInt(v[i]);
}
raf.close();
raf = new RandomAccessFile("datiRandom.dat", "r");
System.out.println("Il file è grande: " + raf.length() + "bytes");
int first, last;
// readInt legge un numero intero dal file
first = raf.readInt();
// seek permette di muoversi all'interno del file
raf.seek(raf.length() - 4);
last = raf.readInt();
raf.close();
System.out.println("Il primo numero vale: " + first);
System.out.println("L'ultimo numero vale: " + last);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Lettura e Scrittura su File
Di seguito è riportato un semplice esempio per la gestione dell'input/output da file, sia di testo, sia binario. Le classi utilizzate per implementare la classe qui riportata sono:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
public class GestioneFile {
String textFileName = "testo.txt";
String binaryFileName = "binario.dat";
public void printFile() {
try {
PrintWriter output = new PrintWriter(textFileName);
output.print("Stampa su file di una stringa di testo");
output.close();
} catch (FileNotFoundException e) {
// Blocco di gestione delle eccezioni
e.printStackTrace();
}
}
public String readFromFile() {
String line = null;
try {
// Lettura di input da console
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
line = console.readLine();
System.out.println(line);
// Lettura di input da file
BufferedReader fileReader = new BufferedReader(new FileReader(new File(textFileName)));
// Lettura di un singolo carattere
char c = (char)fileReader.read();
System.out.print(c);
// Lettura di una riga di testo
line = fileReader.readLine();
fileReader.close();
console.close();
} catch (IOException e) {
// Blocco di gestione delle eccezioni
e.printStackTrace();
}
return line;
}
public void writeBinaryFile() {
int[] v = new int[] {1000,2,3,4,5,6,7,8,9,10};
try {
RandomAccessFile binaryFile = new RandomAccessFile(new File(binaryFileName), "rw");
for (int i = 0; i < 10; i++) {
binaryFile.writeInt(v[i]);
}
binaryFile.close();
} catch (Exception e) {
// Blocco di gestione delle eccezioni
e.printStackTrace();
}
}
public void readBinaryFile() {
try {
File file = new File(binaryFileName);
RandomAccessFile binaryFile = new RandomAccessFile(file, "r");
int numIntegers = (int)file.length()/4;
int[] v = new int[numIntegers];
for (int i = 0; i < numIntegers; i++) {
v[i] = binaryFile.readInt();
}
binaryFile.close();
// Stampa il vettore acquisito
for (int i = 0; i < numIntegers; i++) {
System.out.print(v[i] + " ");
}
} catch (Exception e) {
// Blocco di gestione delle eccezioni
e.printStackTrace();
}
}
}
Di seguito la classe Principale che implementa il metodo main nel quale vengono richiamate le funzioni della classe Gestione File precedentemente introdotta.
public class Principale {
public static void main(String[] args) {
GestioneFile f = new GestioneFile();
f.printFile();
String l = f.readFromFile();
System.out.println(l);
f.writeBinaryFile();
f.readBinaryFile();
}
}