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