/* ************************************************************************* * Ora parleremo dell'I/O, ossia Input/Output (Entrata/Uscita). * Il sistema I/O del Java ha un'interfaccia indipendente dall'hardware, * analoga a quella UNIX del C, che pone un certo livello di astrazione tra * il programmatore e il dispositivo in uso, per cui e' analogo accedere a * terminali connessi in rete, unita' a disco, a nastro, eccetera. * I diversi dispositivi sono considerati un dispositivo logico chiamato * FLUSSO (detto stream o pipe). I flussi partono da una sorgente ed arrivano * ad una destinazione, astraendosi dai dispositifi fisici che lo permettono. * I tipi di flusso in UNIX/ANSI C sono 2: * * 1) FLUSSO DI TESTO: e' una sequenza di caratteri, che pero' durante il * trasferimento puo' subire anche delle conversioni secondo le necessita' * dell'ambiente di destinazione (ad esempio il carattere di fine riga e' * diverso in certi casi: puo' essere di newline o cr+lf) il che implica * che il flusso eventualmente convertito puo' essere anche di dimensione * diversa. Passando un file non di testo da questo flusso si danneggia! * * 2) FLUSSO BINARIO: e' una sequenza di byte avente una corrispondenza uno * a uno con la sequenza rivevuta dal dispositivo esterno. Non avvenendo * alcuna conversione il numero di byte scritti/letti rimane uguale. * * In java sono disponibili anche flussi filtrati piu' sofisticati. * Abbiamo gia' visto comandi per I/O da e verso la console (tastiera/video). * Ora vedremo il caso di lettura/scrittura di file. * In Java le superclassi da cui sono derivati i vari flussi particolari * sono InputStream e OutputStream. Le subclassi che ci interessano sono * FileInputStream e FileOutputStream, dedicate al flusso di file. * Ad esempio: * * FileInputStream MioInFilStr = new FileInputStream("Jlez6a.java"); * FileOutputStream MioOutFilStr = new FileOutputStream("Jlez6a.bak"); * * Queste classi pero' hanno metodi che possono leggere e scrivere soltanto * bytes, e non altri tipi di dati. Se si desiderano leggere/scrivere degli * int, dei float, o altri dati, si puo' convertire/filtrare lo stream usando * delle classi come DataInputStream: * * DataInputStream MioInDatStr = new DataInputStream(MioInFilStr); * DataOutputStream MioOutDatStr = new DataOutputStream(MioOutFilStr); * * A questo punto saranno disponibili dei metodi piu sofisticati: readChar(), * readBoolean(), readFloat(), readLine(); writeChar(), writeFloat(), ecc. * Comunque, per maggiore semplicita', leggeremo e scriveremo bytes, usando * direttamente InputStream e OutputStream, per creare una copia di questo * file sorgente (Jlez6a.java) chiamata Jlez6a.bak. * Le eccezioni generate da queste classi sono di tipo IOException: * * try { * MioInFilStr = new FileInputStream("Jlez6a.java"); * } * catch (IOException e) { * System.out.println("Errore: " + e + " nella lettura di un file"); * System.exit(0); * } * * Attenzione che si scrive su HD, io vi ho avvertito! ************************************************************************* */ import java.io.*; // Include le funzioni I/O standard di base. class Jlez6a { // Da qua inizia la classe Jlez6a public static void main(String args[]) // Definiamo il metodo Main. { // Inizio del main() // Gli input/output stream e la variabile LungFile li dichiaro nel main(), // in modo che siano accessibili ovunque. Se fossero dichiarati all'interno // di un blocco { } di un try o del for, all'esterno di tale blocco non // esisterebbero. Fate attenzione a questo fatto quando decidete dove // dichiarare variabili/oggetti! Dichiarateli localmente solo se sono // effettivamente usati esclusivamente all'interno del blocco. Per esempio // la variabile i usata nel for e' dichiarata (e usabile) solo nel blocco // del for, perche' effettivamente non viene usata mai fuori da esso. FileInputStream MioInFilStr = null; FileOutputStream MioOutFilStr = null; int LungFile = 0; // Provo ad aprire il file Jlez6a.java in lettura con FileInputStream. try { MioInFilStr = new FileInputStream("Jlez6a.java"); } catch (IOException e) { System.out.println("Errore: " + e + " nella lettura di un file"); System.exit(0); } // Provo ad aprire/creare Jlez6a.bak in scrittura con FileOutputStream. try { MioOutFilStr = new FileOutputStream("Jlez6a.bak"); } catch (IOException e) { System.out.println("Errore: " + e + " nella creazione di un file"); System.exit(0); } // Se sono arrivato qua senza eccezioni, ho i 2 flussi (stream) attivi. // Per creare il file di copia bastera' leggere dalla sorgente e scrivere // nella destinazione tutti i bytes, uno alla volta. // Per sapere quanti byte posso copiare (cioe' la lunghezza del file) uso // il metodo int available(). try { LungFile = MioInFilStr.available(); // Mi informo sul num. bytes. } catch (IOException e) { System.out.println("Errore: " + e + " determinando la lungh. di un file"); System.exit(0); } // Per leggere/scrivere uso FileInputStream.read(), FileOutPutStream.write(). // So quanti bytes devo copiare, grazie ad available(). try { for(int i=0; i<LungFile; i++) { MioOutFilStr.write(MioInFilStr.read()); // copio un byte. } } catch (IOException e) { System.out.println("Errore: " + e + " nella copia di un file"); System.exit(0); } // File copiato, posso chiudere i due flussi (stream). try { MioInFilStr.close(); // Chiudo l'InputStream. MioOutFilStr.close(); // Chiudo l'OutputStream. } catch (IOException e) { System.out.println("Errore: " + e + " nella chiusura di un file"); System.exit(0); } // Scriviamo un messaggio di felicitazioni System.out.print("File copiato, " + LungFile + " bytes,"); System.out.println(" suffisso copia: .bak"); } // Fine del metodo principale Main() } // Fine della classe Jlez6a