Lettura di Files con classe Scanner e classe File Innanzi tutto un ripasso sulla classe Scanner dall’help di java: java.util Class Scanner java.lang.Object java.util.Scanner All Implemented Interfaces: Iterator<String> public final class Scanner extends Object implements Iterator<String> A simple text scanner which can parse primitive types and strings using regular expressions. A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods. For example, this code allows a user to read a number from System.in: Scanner sc = new Scanner(System.in); int i = sc.nextInt(); As another example, this code allows long types to be assigned from entries in a file myNumbers: Scanner sc = new Scanner(new File("myNumbers")); while (sc.hasNextLong()) { long aLong = sc.nextLong(); } The scanner can also use delimiters other than whitespace. This example reads several items in from a string: String input = "1 fish 2 fish red fish blue fish"; Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*"); System.out.println(s.nextInt()); System.out.println(s.nextInt()); System.out.println(s.next()); System.out.println(s.next()); s.close(); prints the following output: 1 2 red blue The same output can be generated with this code, which uses a regular expression to parse all four tokens at once: String input = "1 fish 2 fish red fish blue fish"; Scanner s = new Scanner(input); s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)"); MatchResult result = s.match(); for (int i=1; i<=result.groupCount(); i++) System.out.println(result.group(i); s.close(); The default whitespace delimiter used by a scanner is as recognized by Character.isWhitespace. A scanning operation may block waiting for input. The next() and hasNext() methods and their primitive-type companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext and next methods may block waiting for further input. Whether a hasNext method blocks has no connection to whether or not its associated next method will block. Tra i costruttori della classe Scanner vedo: a) Scanner(File source) Constructs a new Scanner that produces values scanned from the specified file. Ecco cosa possiamo usare per leggere un file!! Dopo vedremo meglio.. b) Scanner(InputStream source) Constructs a new Scanner that produces values scanned from the specified input stream. System.in è un oggetto della classe InputStream. Quindi questa è la descrizione del costruttore che usiamo noi per leggere l’input dato dall’utente da tastiera!! Scanner sc= new Scanner(System.in) c) Scanner(String source) Constructs a new Scanner that produces values scanned from the specified string. Questo costruttore mi dice che un oggetto di classe Scanner può essere utilizzato anche su oggetti di classe stringa. Es.: ESEMPIO: String line= “Voglio dividere queste parole”; Scanner sc=new Scanner(line); while (sc.hasNext()){ System.out.println(sc.next()); } sc.close(); -----------------------------------------------------------------------------ATTT!! RICORDATE!!! Uno Scanner va sempre chiuso (invocando il metodo close sull’oggetto di tipo Scanner) dopo il suo utilizzo! Andiamo a vedere l’help in linea della classe Scanner: _______________________________________________________________________ _______________________________________________________________________ public void close() Closes this scanner. If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close method will be invoked. If this scanner is already closed then invoking this method will have no effect. Attempting to perform search operations after a scanner has been closed will result in an IllegalStateException. Specified by: close in interface Closeable Specified by: close in interface AutoCloseable _______________________________________________________________________ _______________________________________________________________________ String lineNum= “3 4 -67 11 45 -89 22 2”; Scanner sc=new Scanner(lineNum); int sum=0; while (sc.hasNextInt()){ sum= sum+ sc.nextInt(); } sc.close(); System.out.println(“La somma dei numeri Interi trovati nella Stringa è: ” + sum); ----------------------------------------------------------------------Questi esempi mostrano che invece di uno StringTokenizer potete usare uno Scanner per determinare gli elementi di una Stringa (separati da spazi o altri delimitatori). java.io Class File java.lang.Object java.io.File An abstract representation of file and directory pathnames. L’unico costruttore che ci serve: File(String pathname) Creates a new File instance by converting the given pathname string into an abstract pathname. ESEMPIO: import java.io.IOException; import java.io.File; public class Soluzione{ public static void main(String [] args) throws IOException{ … … File ff=new File(“C:\eserciziJava\prova.txt”); Scanner sc= new Scanner(ff); /* leggo ciò che devo leggere dal file usando I soliti Metodi della classe Scanner */ … sc.close(); // chiudo lo Scanner } } All’interno della classe Soluzione creo un oggetto della classe File che rappresenta il file prova.txt (che si trova nella directory “C:\eserciziJava”). ATTENZIONE!! in tale comando ho usato un pathname assoluto, ma potrei anche usare il pathname relativo alla directory in cui si trova il file .java in cui sto scrivendo l’implementazione della mia classe!!!. Più semplicemente, se il file “prova.txt” si trovasse nella stessa directory del file “.java” che invoca la creazione di oggetto della classe File (ovvero se avessi un file Soluzione.java nella directory “C:\eserciziJava”), in tale File potrei usare semplicemente il pathname relativo, che consiste nel solo nome del file! File ff=new File(“prova.txt”); Se invece, il file “Soluzione.java” fosse in “C:\eserciziJava” e il file “prova.txt” fosse nella directory “C:\eserciziJava\fileTesto” che è una sottodirectory di “C:\eserciziJava”, nel file “Soluzione.java” potrei usare: - pathname assoluto File ff=new File(“C:\eserciziJava\fileTesto\prova.txt”); - pathname relativo File ff=new File(“fileTesto\prova.txt”); ATTENZIONE PERO’ alle Eccezioni! L’utente potrebbe essere distratto e non ricordarsi di mettere il file nella posizione in cui il programma se lo aspetta (in questo caso vorrebbe dire che la classe Soluzione durante la sua esecuzione non trova il file “prova.txt” in “C:\eserciziJava\fileTesto”. Cosa succede? La classe il comando new File(…) non trovando il File, il cui nome è specificato dalla Stringa che riceve come argomento, “lancia” al metodo chiamante una FileNotFoundException() che è una sottoclasse di IOException() (quindi più semplicemente posso dire che viene generata una IOException()…) ATTENZIONE che un metodo che potrebbe generare, altrimenti detto “lanciare”, una IOException deve dichiararlo (notate la riga di dichiarazione del metodo main) con la clausula public void nomemetodo(parametri) throws IOException{ … … … } Allo stesso modo, supponiamo che la classe A in un suo metodo invochi il metodo di un oggetto di classe B, e tale metodo possa lanciare una IOException alla classe A. In tal caso, durante l’esecuzione del generata una IOException dalla classe l’accezione lanciata dal metodo della al metodo chiamante! Quindi anche il metodo della classe A deve quindi dichiararlo! metodo della classe A, se viene B, il metodo della classe A riceve classe B, e la lancia a sua volta potrebbe generare l’eccezione e ESEMPIO: import java.io.IOException; import java.io.File; import java.util.Scanner; public class ClasseB{ public int apriFile(String nomeFile) throws IOException{ //l’intestazione di apriFile() dice che questo metodo //potrebbe lanciare eccezioni … File ff= new File(nomeFile); //potrebbe lanciare eccezioni a chi chiama … Scanner sc= new Scanner(ff); … } … } import java.io.IOException; public class ClasseA{ public int metodoA(String nomef) throws IOException{ /*l’intestazione di metodoA() dice che questo metodo potrebbe lanciare eccezioni*/ … … ClasseB cB=new ClasseB(); cB.apriFile(nomef); /*Le eccezioni dichiarate nella intestazione potrebbero derivare da questo comando!*/ } … } import java.io.IOException; public class Soluzione{ public static void main(String [] args) throws IOException{ /*l’intestazione di main() dice che questo metodo potrebbe lanciare eccezioni*/ … String nomef=“prova.txt”; ClasseA cA=new ClasseA(); cA.metodoA(nomef); /*Le eccezioni dichiarate nella intestazione potrebbero derivare da questo comando!*/ } … } RIASSUMENDO: Lettura dal file “mioFile.txt”: … File ffR=new File(‘‘mioFile.txt’’); Scanner sc= new Scanner(ffR); /* leggo ciò che devo leggere dal file usando i soliti Metodi della classe Scanner */ … … sc.close(); // chiudo lo Scanner ... Essendosi ricordati di: 1) importare le librerie necessarie; a. import java.io.IOException; b. import java.io.File; c. import java.util.Scanner; 2) dichiarare e/o gestire le eventuali e opportune eccezioni Scrittura (e/o creazione) di Files con classe File e PrintStream Per la scrittura da files, valgono gli stessi discorsi fatti sulle eccezioni ma si deve usare un oggetto di classe PrintStream che permette di usare le istruzioni di output che gia’ conosciamo: print e println()… comandi: ... String nfW= ’’mioFile.txt’’; File ffW = new File(nfW); if (ffW.exists()==false){ ffW.createNewFile(); // se il file non esiste lo creo }else{ System.out.println(‘‘il file esiste: sovrascrivero!’’); } FileOutputStream fOS = new FileOutputStream(ffW); PrintStream outF = new PrintStream(fOS); /* ricordo che anche System.out e’ di una istanza di PrintStream*/ outF.println("Whatever… "); /* scrivo su outF come fosse System.out*/ outF.print("Whatever… "); … Essendosi ricordati di: 1) importare le librerie necessarie; // per scrittura su files a. import java.io.IOException; b. import java.io.File; c. import java.io.PrintStream; d. import java.io.FileOutputStream; // se usate anche la classe scanner per operazioni di input\output e. import java.util.Scanner; 2) dichiarare e/o gestire le eventuali e opportune eccezioni