Informatica I Ingegneria Medica Prof. Diego Salamon Gestione I/O Prof. Diego Salamon Introduzione Nella creazione e gestione del software è necessario interagire con entità esterne a quelle del programma che andiamo a implementare. E’ necessario cioè creare dei canali di comunicazione che permettano agli algoritmi implementati di scambiare informazioni con l’utente e di restituire risultati Leggere dati in ingresso Mentre la stampa di stringhe (output verso il monitor) è agevole tramite il metodo 1. 2. 3. System.out.println(…); L’input da tastiera necessita di qualche operazioni aggiuntiva: Importiamo la classe Scanner Istanziamo un oggetto di questa classe Utilizziamo i metodi che la classe mette a disposizione La classe Scanner Permette la lettura dei dati da tastiera E’ presente dalla versione 5 di Java Importo la classe: import java.util.Scanner Istanzio l’oggetto: Scanner in = new Scanner (System.in); In dipendenza del dato in ingresso la classe mette a disposizione i seguenti metodi: nextInt();// per ricevere in ingresso degli interi nextDouble(); // per ricevere in ingresso dei double nextLine(); // per ricevere in ingresso delle stringhe Il programma sa che l’immissione da tastiera è terminata dopo la pressione del tasto enter Esempio import java.util.Scanner Public class tester{ public class void main(String [] args) { Scanner in = new Scanner(System.in); System.out.println(“Inserisci un valore:”); int quantity = in.nextInt(); } } Generalizzazioni Le istanze della classe scanner possono essere diverse; nel caso di input da tastiera istanzio un oggetto di questa classe passando al costruttore come parametro l’oggetto System.in. Questo mi permette di utilizzare la classe per l’input da tastiera La stessa classe Scanner la posso utilizzare per gestiore I/O su file passando al costruttore un altro oggetto come parametro File e Flussi Una delle attività più utili e frequenti nella programmazione è l’interazione tra i programmi e i file. I file possono essere organizzati in diversi modi. File di testo (come i sorgenti java) File binari (serializzati, o non) Gli oggetti coinvolti Anche in questo caso usiamo la classe scanner, istanziato con l’oggetto FileReader. L’oggetto FileReader si aspetta come parametro costruttore il nome del file presente sul file system per la lettura e/o la scrittura FileReader reader = new FileReader(“input.txt”); Scanner in = new Scanner(reader); Lettura da File Istanziati gli oggetti reader e in possiamo utilizzare i metodi già visti per l’input da tastiera per leggere dal file(next, nextLine, nextInt, nextDouble) import java.util.Scanner Import java.io.FileReader Public class tester{ public class void main(String [] args) { FileReader reader= new FileReader(“input.txt”); Scanner in = new Scanner(reader); System.out.println(“Inserisci un valore:”); int quantity = in.nextInt(); } } Scrittura su File La scrittura su file utilizza una classe ancora diversa, PrintWriter PrintWriter out = new PrintWriter(“output.txt”) Se il file su cui scrivere esiste già viene svuotato prima di scrivervi nuovi dati, se non esiste viene creato. I metodi da utlizzare per scrivere su file sono: out.println(“…”); out.print(“…”); Ogni flusso dati in scrittura utilizzante l’oggetto PrintWriter deve essere chiuso: out.close Esempio 01: import java.io.FileReader; 02: import java.io.PrintWriter; 03: import java.util.Scanner; 04: 05: public class LineNumberer 06: { 07: public static void main(String[] args) 08: { 09: Scanner console = new Scanner(System.in); 10: System.out.print("Input file: "); 11: String inputFileName = console.next(); 12: System.out.print("Output file: "); 13: String outputFileName = console.next(); 14: // SEGUE Esempio 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: FileReader reader = new FileReader(inputFileName); Scanner in = new Scanner(reader); PrintWriter out = newPrintWriter(outputFileName); int lineNumber = 1; while (in.hasNextLine()) { String line = in.nextLine(); out.println("/* " + lineNumber + " */ " + line); lineNumber++; } out.close(); } File e Formati Esistono due modi fondamentali per memorizzare i dati: Modo tipo Testo Modo di tipo Binario Nel formato testo i dati sono memorizzati e rappresentati in forma leggibile, come sequenze di caratteri Nel formato binario i dati sono rappresentati da sequenze di byte File di Tipo Binario Se si utilizza la modalità binaria le classi viste vanno sostituite con le rispettive che gestiscono gli stream di dati: FileInputStream FileOutputStream FileInputStream inputstream=new FileInputStream(“input.bin”); FileOutputStream outputstream=new FileOutputStream(“output.bin”); La classe InputStream ha un metodo read per leggere un byte per volta Analogamente la classe OutputStream ha un metodo per scrivere un byte per volta. int next inpustream.read(); Per verificare la fine del flusso occorre controllare che next != -1 Esempio import java.io.FileInputStream; import java.io.FileOutputStream; public class Tester { public void TestFile(String inFile, String outFile) { FileInputStream in = null; FileOutputStream out = null; in = new FileInputStream(inFile); out = new FileOutputStream(outFile); TesterStream (in,out); } Esempio public void TesterStream(FileInputStream in, FileOutputStream out) { boolean done = false; while (!done) { int next = in.read(); if (next == -1) done = true; else { byte b = (byte) next; out.write(b); } } } Esempio import java.util.Scanner; public class EncryptorTester { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Input file: "); String inFile = in.next(); System.out.print("Output file: "); String outFile = in.next(); Tester prova= new Tester(); prova.TestFile(inFile, OutFile); } } Accesso Casuale e Sequenziale Sequential access Un file è acceduto un byte per volta Può essere un modo di procedere inefficiente Random access Permette l’accesso a posizioni arbitrarie del file Solo I file permettono l’accesso casuale System.in e System.out non possono Per ogni file aperto esiste uno speciale puntatore della posizione corrente del file E’ possibile leggere o scrivere dalla posizione corrente del puntatore. Gli esempi visti sino ad ora erano implementazioni di accessi sequenziali Accesso Casule e sequenziale File ad Accesso Casuale Java per permettere l’accesso casuale mette a disposizione un classe RandomAccessFile Import java.io.RandomAccessFile; Per aprire un file ad accesso casuale dobbiamo fornire un nome al file e indicare la modalità di apertura: “r” o “rw” RandomAccessFile f = new RandomAccessFile(“prova.dat","rw"); File ad Accesso Casuale L’invocazione del metodo f.seek(); Sposta il puntaotore al byte di indice n contando le posizioni dall’inizio del file per sapere quale è la posizione corrente del puntatore del file esiste il metodo: f.getFilePointer(); Per sapere quanto è lungo un file si usa il metodo length f.length La classe RandomAccessFile memorizza i dati in formato binario File ad Accesso Casuale La classe RandomAccessFile mette a disposizione i metodi: readInt e writeInt o readDouble e writeDouble per leggere e/o scrivere su file double x = f.readDouble(); f.writeDouble(x);