Eccezioni – Precisazioni e approfondimenti
„
Costruttore: il parametro String definisce il messaggio di errore
associato all’eccezione
„
Metodi particolarmente significativi
… getMessage(): ritorna l’istanza di String con il messaggio di errore
specificato all’istanziazione dell’oggetto
… printStackTrace(): stampa lo Stack Trace permettendo di
individuare metodo e linea di codice che ha lanciato l’eccezione
(utile per il debug)
… getStackTrace(): ritorna un array di StackTraceElement –
l’elemento di indice zero è la cima dello stack
… fillInStackTrace(): genera l’array di StackTraceElement accessibile
mediante getStackTrace() o il cui contenuto è stampato da
printStackTrace (attenzione: diverso da setStackTrace!)
„
Classe StackTraceElement: rappresenta un’invocazione di metodo (a
parte l’elemento in cima allo stack che è il metodo in esecuzione e da
cui viene generato l’oggetto Throwable)
Esercizio 3: filtraggio file di testo
Dall’esercizio 3 dell’esecitazione n.5:
“Realizzare un’applicazione Java in grado di cercare una
qualunque parola all’interno del file testo.txt allegato a
queste slide, contando il numero di occorrenze.
L’applicazione deve inoltre essere in grado di creare un
nuovo file testo2.txt ottenuto da testo.txt sostituendo a
tutte le occorrenze di un vocabolo il medesimo vocabolo con
però tutte le lettere maiuscole.”
La lettura delle specifiche permette di definire, a livello
astratto, l’esistenza di un componente in grado di svolgere
due operazioni (ricerca di una parola con conteggio delle
occorrenze; sostituzione delle occorrenze di un vocabolo)
Soluzione: il componente
package esercitazioni05.filtro;
import java.io.*;
import java.util.StringTokenizer;
public class TextFileAnalyzer {
private File file; // la classe file implementa un oggetto con le
// caratteristiche di un file (vedi java.io)
public TextFileAnalyzer(String fileName) throws FileNotFoundException {
file = new File(fileName);
if (! file.exists())
throw new FileNotFoundException("Il file " + fileName + "non esiste");
}
Nota: se si fosse gestita l’eccezione dentro il costruttore (anziché lanciarla), si
avrebbe un comportamento cablato nell’oggetto, cosa che impedirebbe a chi
crea l’istanza di prendere diverse contromisure in caso di “file non trovato”
StringTokenizer
La classe java.util.StringTokenizer permette di spezzare una stringa
in più sottostringhe (token) distinguibili perché delimitate da caratteri
considerati come separatori
Costruttore
StringTokenizer(String s, String delim, boolean returnDelims)
StringTokenizer(String s, String delim)
StringTokenizer(String s)
I separatori sono i singoli caratteri della stringa delim; nel caso si
ricorra al costruttore ad un parametro, delim è automaticamente
impostata al valore di default: “ \t\n\r\f” (nota: \t, \n, \r, \f sono
considerati come singoli caratteri)
Metodi significativi (di veda la documentazione sulle API Java)
ƒ hasMoreToken(): true se la stringa contiene altri token
ƒ nextToken(): restituisce il token
ƒ nextToken(String delim): restituisce il token individuato usando
come separatori quelli del parametro delim (quello del metodo, non
del costruttore!)
Soluzione: la funzionalità (metodo) di ricerca
public int searchWord(String word) throws IOException {
BufferedReader lineReader = new BufferedReader(new FileReader(file));
int counter = 0;
String line, token;
StringTokenizer tokenizer;
do {
line = lineReader.readLine();
if (line != null) {
tokenizer = new StringTokenizer(line, " \n"); // delimitatori
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
if (token.equals(word)) counter++;
}
}
} while (line != null);
return counter;
}
Soluzione: il metodo di ricerca e sostituzione
public void replaceWord(String originalWord, String newWord) throws
IOException {
BufferedReader lineReader = new BufferedReader(new
FileReader(file));
BufferedWriter lineWriter = new BufferedWriter(new
FileWriter(file.getParent()+File.separator+"testo2.txt"));
String originalLine, newLine, token;
StringTokenizer tokenizer;
La scelta di usare BufferedReader e BufferedWriter deriva dalla
disponibilità di metodi “comodi” per l’applicazione, quali la lettura per
linee e la corretta scrittura del newLine.
Soluzione: il metodo di ricerca e sostituzione
do {
originalLine = lineReader.readLine();
editedLine= "";
if (originalLine != null) {
tokenizer = new StringTokenizer(originalLine, " \n",true);
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
if (token.equals(originalWord))
editedLine= editedLine + newWord;
else
editedLine= editedLine+ token;
}
lineWriter.write(editedLine);
lineWriter.newLine();
lineWriter.flush(); // altrimenti il buffer non scrive i dati sul file
}
} while (originalLine != null);
Soluzione: il main
public class RunTextFileAnalyzer {
public static void main(String[] args) {
TextFileAnalyzer analyzer;
String input;
boolean searchAgain = true;
// INPUT DA CONSOLE
BufferedReader stdInput = new
BufferedReader(newInputStreamReader(System.in));
try {
while (searchAgain) {
analyzer = new TextFileAnalyzer(args[0]);
System.out.print("Inserire parola da cercare: ");
input = stdInput.readLine();
if (input.equals("end_search"))
searchAgain = false;
else
System.out.println("Numero occorrenze di " + input + " " +
analyzer.searchWord(input));
} // fine while
Soluzione: il main
// occorre creare una nuova istanza di TextFileAnalyzer perché il
// BufferedReader usato internamente non permette di riportare il puntatore
// all’inizio del file
analyzer = new TextFileAnalyzer(args[0]);
String oldWord, newWord;
System.out.print("Inserire parola da rimpiazzare: ");
oldWord = stdInput.readLine();
System.out.print("Inserire parola sostitutiva: ");
newWord = stdInput.readLine();
analyzer.replaceWord(oldWord, newWord);
}
catch (IOException e) {
System.err.println("Attezione: " + e.getMessage());
}
} // fine main
Scarica

file PDF