I File in Java

Da Bioingegneria Elettronica e Informatica.

Vitoantonio Bevilacqua vitoantonio.bevilacqua@poliba.it

Antonio Brunetti antonio.brunetti@poliba.it

Gianpaolo Francesco Trotta gianpaolofrancesco.trotta@poliba.it

Pagina in lavorazione

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

  1. import java.io.*;
  2.  
  3. public class Principale {
  4.  
  5. 	public static void main(String[] args) {
  6. 		new Principale().run();
  7. 	}
  8.  
  9. 	public void run() {
  10. 		/* Per la lettura e scrittura di file,
  11. 		 * si utilizzano le classi di java.io:
  12. 		 * - FileReader (FileInputStream)
  13. 		 * - FileWriter (FileOutputStream)
  14. 		 * che permettono di gestire l'I/O di caratteri o bytes
  15. 		 */
  16.  
  17. 		FileReader file;
  18. 		try {
  19. 			// Lettura di file di testo con due letture successive
  20. 			file = new FileReader("dati.txt");
  21. 			int carattere = file.read();
  22. 			int carattere2 = file.read();
  23.  
  24. 			System.out.println("Il codice del carattere vale: " + carattere);
  25. 			System.out.println("Il codice del carattere vale: " + carattere2);
  26. 			file.close();
  27.  
  28. 			// Lettura di tutto il contenuto del file di testo con ciclo while
  29. 			file = new FileReader("dati.txt");
  30. 			// Letura di tutti i caratteri all'interno di un file di testo
  31. 			int next = file.read();
  32. 			while(next != -1) {
  33. 				char nextc = (char) next;
  34.                 System.out.print(nextc); // stampa il carattere
  35.                 next = file.read(); // legge il prossimo carattere
  36. 			}
  37. 			file.close();
  38.  
  39. 		} catch (IOException e) {
  40. 			// TODO Auto-generated catch block
  41. 			e.printStackTrace();
  42. 		}
  43. 	}
  44. }

Scrittura su file di testo

  1. import java.io.FileWriter;
  2. import java.io.IOException;
  3. import java.util.Scanner;
  4.  
  5. public class Principale2 {
  6.  
  7. 	public static void main(String[] args) {
  8. 		// TODO Auto-generated method stub
  9. 		new Principale2().run();
  10. 	}
  11.  
  12. 	public void run() {
  13. 		/* Per la lettura e scrittura di file,
  14. 		 * si utilizzano le classi di java.io:
  15. 		 * - FileReader (FileInputStream)
  16. 		 * - FileWriter (FileOutputStream)
  17. 		 * che permettono di gestire l'I/O di caratteri o bytes
  18. 		 */
  19.  
  20. 		FileWriter file;
  21. 		Scanner s = new Scanner(System.in);
  22. 		try {
  23. 			// Scrittura su file di testo di numeri acquisiti da tastiera
  24. 			file = new FileWriter("dati_output.txt");
  25.  
  26. 			String num = s.nextLine();
  27. 			while(!num.equals("-1")) {
  28. 				file.write(num + " ");
  29. 				num = s.nextLine();
  30. 			}
  31.  
  32. 			file.close();
  33.  
  34. 			System.out.println("Dati scritti e file chiuso");
  35.  
  36. 		} catch (IOException e) {
  37. 			e.printStackTrace();
  38. 		}
  39. 	}
  40. }

Scrittura e lettura con file binari

  1. import java.io.FileInputStream;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;
  4. import java.util.Scanner;
  5.  
  6. public class Principale3 {
  7.  
  8. 	public static void main(String[] args) {
  9. 		// TODO Auto-generated method stub
  10. 		new Principale3().run();
  11. 	}
  12.  
  13. 	public void run() {
  14. 		/* Per la lettura e scrittura di file,
  15. 		 * si utilizzano le classi di java.io:
  16. 		 * - FileReader (FileInputStream)
  17. 		 * - FileWriter (FileOutputStream)
  18. 		 * che permettono di gestire l'I/O di caratteri o bytes
  19. 		 */
  20.  
  21. 		FileOutputStream fileOutput;
  22. 		Scanner s = new Scanner(System.in);
  23. 		try {
  24. 			// Scrittura su file binario di numeri acquisiti da tastiera
  25. 			fileOutput = new FileOutputStream("dati_output.dat");
  26.  
  27. 			int num = s.nextInt();
  28. 			while(num != -1) {
  29. 				fileOutput.write(num);
  30. 				num = s.nextInt();
  31. 			}
  32.  
  33. 			fileOutput.close();
  34. 			System.out.println("Dati scritti e file chiuso");
  35.  
  36. 			FileInputStream fileInput;
  37. 			fileInput = new FileInputStream("dati_output.dat");
  38.  
  39. 			int numR = fileInput.read();
  40. 			while (numR != -1) {
  41. 				System.out.println("Il numero letto vale: " + numR);
  42. 				numR = fileInput.read();
  43. 			}
  44. 			fileInput.close();
  45. 			System.out.println("Raggiunta fine del file");
  46.  
  47. 		} catch (IOException e) {
  48. 			// TODO Auto-generated catch block
  49. 			e.printStackTrace();
  50. 		}
  51. 	}
  52. }

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

  1. import java.io.BufferedWriter;
  2. import java.io.FileWriter;
  3. import java.io.IOException;
  4. import java.io.PrintWriter;
  5. import java.util.Scanner;
  6.  
  7. public class Principale4 {
  8.  
  9. 	public static void main(String[] args) {
  10. 		// TODO Auto-generated method stub
  11. 		new Principale4().run();
  12. 	}
  13.  
  14. 	public void run() {
  15. 		/* Le classi FileReader e FileWriter forniscono i metodi di base 
  16. 		 * per leggere o scrivere caratteri su file. 
  17. 		 * Non è conveniente usarle direttamente nei programmi perché 
  18. 		 * non permettono di leggere/scrivere direttamente 
  19. 		 * dati più complessi come stringhe e numeri.
  20. 		 */
  21.  
  22. 		/* Per ovviare a questo problema di possono utilizzare classi che
  23. 		 * implementano funzionalità di I/O più avanzate.
  24. 		 * - BufferedReader
  25. 		 * - BufferedWriter 
  26. 		 * usano un buffer per memorizzare temporaneamente i caratteri da leggere/scrivere, 
  27. 		 * in modo da ridurre il numero di accessi al file;
  28. 		 * 
  29. 		 * - PrintWriter 
  30. 		 * fornisce i metodi print e println, che permettono di scrivere qualunque dato Java, 
  31. 		 * convertendolo automaticamente in stringa.
  32. 		 */
  33.  
  34. 		// Scrittura di dati su file
  35. 		FileWriter fileOutput;
  36. 		BufferedWriter bufferWriter;
  37. 		PrintWriter printWriter;
  38. 		Scanner s = new Scanner(System.in);
  39. 		try {
  40. 			// Scrittura su file testo di numeri acquisiti da tastiera
  41. 			fileOutput = new FileWriter("dati_output2.txt");
  42. 			bufferWriter = new BufferedWriter(fileOutput);
  43. 			printWriter = new PrintWriter(bufferWriter);
  44.  
  45. 			int num = s.nextInt();
  46. 			while(num != -1) {
  47. 				printWriter.println(num);
  48. 				num = s.nextInt();
  49. 			}
  50.  
  51. 			System.out.println("Dati scritti");
  52.  
  53. 			// Proviamo con un vettore
  54. 			int[] v = {1, 2, 3, 4, 5};
  55. 			// L'istruzione seguente non stampa gli elementi del vettore, ma solo il valore utilizzato come reference
  56. 			printWriter.print(v);
  57. 			/* Il seguente ciclo for permette la stampa su file di testo degli elementi contenuti nel vettore
  58. 			 * for (int i = 0; i < 5; i++) {
  59. 			 * 		printWriter.print(v[i] + " ");
  60. 			 * 	}
  61. 			 */
  62. 			System.out.println("Vettore scritto");
  63. 			printWriter.close();
  64.  
  65. 		} catch (IOException e) {
  66. 			// TODO Auto-generated catch block
  67. 			e.printStackTrace();
  68. 		}
  69. 	}
  70. }

Lettura bufferizzata da file di testo

  1. import java.io.BufferedReader;
  2. import java.io.FileReader;
  3. import java.io.IOException;
  4.  
  5. public class Principale5 {
  6.  
  7. 	public static void main(String[] args) {
  8. 		// TODO Auto-generated method stub
  9. 		new Principale5().run();
  10. 	}
  11.  
  12. 	public void run() {
  13. 		/* Le classi FileReader e FileWriter forniscono i metodi basici 
  14. 		 * per leggere o scrivere caratteri su file. 
  15. 		 * Non è conveniente usarle direttamente nei programmi perché 
  16. 		 * non permettono di leggere/scrivere direttamente 
  17. 		 * dati più complessi come stringhe e numeri.
  18. 		 */
  19.  
  20. 		/* Per ovviare a questo problema di possono utilizzare classi che
  21. 		 * implementano funzionalità di I/O più avanzate.
  22. 		 * - BufferedReader
  23. 		 * - BufferedWriter 
  24. 		 * usano un buffer per memorizzare temporaneamente i caratteri da leggere/scrivere, 
  25. 		 * in modo da ridurre il numero di accessi al file;
  26. 		 * 
  27. 		 * - PrintWriter 
  28. 		 * fornisce i metodi print e println, che permettono di scrivere qualunque dato Java, 
  29. 		 * convertendolo automaticamente in stringa.
  30. 		 */
  31.  
  32. 		// Scrittura di dati da file
  33. 		FileReader fileInput;
  34. 		BufferedReader bufferReader;
  35. 		int i, num;
  36. 		try {
  37. 			// Lettura da file di testo di numeri
  38. 			fileInput = new FileReader("dati_output2.txt");
  39. 			bufferReader = new BufferedReader(fileInput);
  40.  
  41. 			String s = bufferReader.readLine();
  42. 			while (s != null) {
  43. 				System.out.println(s);
  44. 				s = bufferReader.readLine();
  45. 			}
  46.  
  47. 			for (i = 0; i < 10; i++) {
  48. 				// L'istruzione seguente permette di convertire in intero una stringa...
  49. 				// funzioni analoghe esistono per gli altri tipi di valori
  50. 				num = Integer.parseInt(bufferReader.readLine());
  51. 				System.out.println(num);
  52. 			}
  53.  
  54. 			bufferReader.close();
  55. 			fileInput.close();
  56.  
  57. 		} catch (IOException e) {
  58. 			// TODO Auto-generated catch block
  59. 			e.printStackTrace();
  60. 		}
  61. 	}
  62. }

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.

  1. import java.io.IOException;
  2. import java.io.RandomAccessFile;
  3.  
  4. public class Principale6 {
  5.  
  6. 	public static void main(String[] args) {
  7. 		new Principale6().run();
  8. 	}
  9.  
  10. 	public void run() {
  11. 		/* La classe RandomAccessFile permette di istanziare oggetti
  12. 		 * in grado di gestire l'accesso casuale ai file.
  13. 		 * Un oggetto di tipo RandomAccessFile può essere istanziato specificando il percorso del file (o in oggetto di tipo File)
  14. 		 * e la modalità di apertura.
  15. 		 * In questo contesto, le principali modalità di apertura dei file sono:
  16. 		 *  - r: apertura in sola modalità lettura;
  17. 		 *  - rw: apertura in modalità lettura e scrittura. In questo caso, se il file non esiste, esso viene creato.
  18. 		 */
  19.  
  20. 		RandomAccessFile raf;
  21. 		int i, num;
  22. 		try {
  23. 			// Scrittura su file binario di numeri acquisiti da tastiera
  24. 			raf = new RandomAccessFile("datiRandom.dat", "rw");
  25. 			int[] v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  26.  
  27. 			for (i = 0; i < 10; i++) {
  28. 				// writeInt scrive un numero intero sul file
  29. 				raf.writeInt(v[i]);
  30. 			}
  31.  
  32. 			raf.close();
  33.  
  34. 			raf = new RandomAccessFile("datiRandom.dat", "r");
  35. 			System.out.println("Il file è grande: " + raf.length() + "bytes");
  36. 			int first, last;
  37.  
  38. 			// readInt legge un numero intero dal file
  39. 			first = raf.readInt();
  40.  
  41. 			// seek permette di muoversi all'interno del file
  42. 			raf.seek(raf.length() - 4);
  43.  
  44.  
  45. 			last = raf.readInt();
  46. 			raf.close();
  47.  
  48. 			System.out.println("Il primo numero vale: " + first);
  49. 			System.out.println("L'ultimo numero vale: " + last);
  50.  
  51. 		} catch (IOException e) {
  52. 			// TODO Auto-generated catch block
  53. 			e.printStackTrace();
  54. 		}
  55. 	}
  56. }

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:

  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileReader;
  5. import java.io.IOException;
  6. import java.io.InputStreamReader;
  7. import java.io.PrintWriter;
  8. import java.io.RandomAccessFile;
  9.  
  10. public class GestioneFile {
  11.  
  12. 	String textFileName = "testo.txt";
  13. 	String binaryFileName = "binario.dat";
  14.  
  15. 	public void printFile() {
  16. 		try {
  17. 			PrintWriter output = new PrintWriter(textFileName);
  18. 			output.print("Stampa su file di una stringa di testo");
  19. 			output.close();
  20. 		} catch (FileNotFoundException e) {
  21. 			// Blocco di gestione delle eccezioni
  22. 			e.printStackTrace();
  23. 		}
  24. 	}
  25.  
  26. 	public String readFromFile() {	
  27. 		String line = null;
  28. 		try {
  29. 			// Lettura di input da console
  30. 			BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
  31. 			line = console.readLine();
  32. 			System.out.println(line);
  33.  
  34. 			// Lettura di input da file
  35. 			BufferedReader fileReader = new BufferedReader(new FileReader(new File(textFileName)));
  36. 			// Lettura di un singolo carattere
  37. 			char c = (char)fileReader.read();
  38. 			System.out.print(c);
  39. 			// Lettura di una riga di testo
  40. 			line = fileReader.readLine();	
  41.  
  42. 			fileReader.close();
  43. 			console.close();
  44.  
  45.  
  46. 		} catch (IOException e) {
  47. 			// Blocco di gestione delle eccezioni
  48. 			e.printStackTrace();
  49. 		}
  50. 		return line;
  51. 	}
  52.  
  53. 	public void writeBinaryFile() {
  54. 		int[] v = new int[] {1000,2,3,4,5,6,7,8,9,10};
  55. 		try {
  56. 			RandomAccessFile binaryFile = new RandomAccessFile(new File(binaryFileName), "rw");
  57. 			for (int i = 0; i < 10; i++) {
  58. 				binaryFile.writeInt(v[i]);
  59. 			}
  60. 			binaryFile.close();
  61. 		} catch (Exception e) {
  62. 			// Blocco di gestione delle eccezioni
  63. 			e.printStackTrace();
  64. 		}
  65. 	}
  66.  
  67. 	public void readBinaryFile() {
  68. 		try {
  69. 			File file = new File(binaryFileName);
  70. 			RandomAccessFile binaryFile = new RandomAccessFile(file, "r");
  71.  
  72. 			int numIntegers = (int)file.length()/4;
  73. 			int[] v = new int[numIntegers];
  74.  
  75. 			for (int i = 0; i < numIntegers; i++) {
  76. 				v[i] = binaryFile.readInt();
  77. 			}
  78.  
  79. 			binaryFile.close();
  80.  
  81. 			// Stampa il vettore acquisito
  82. 			for (int i = 0; i < numIntegers; i++) {
  83. 				System.out.print(v[i] + " ");
  84. 			}
  85. 		} catch (Exception e) {
  86. 			// Blocco di gestione delle eccezioni
  87. 			e.printStackTrace();
  88. 		}
  89. 	}
  90. }

Di seguito la classe Principale che implementa il metodo main nel quale vengono richiamate le funzioni della classe Gestione File precedentemente introdotta.

  1. public class Principale {
  2.  
  3. 	public static void main(String[] args) { 
  4. 		GestioneFile f = new GestioneFile();
  5. 		f.printFile();
  6.  
  7. 		String l = f.readFromFile();
  8. 		System.out.println(l);
  9.  
  10. 		f.writeBinaryFile();
  11. 		f.readBinaryFile();
  12. 	}
  13. }