giovedì 10 giugno 2010

Java: lettura e scrittura di testo delimitato

I metodi visti per la scrittura e la lettura del testo in un file possono essere utilizzati per la scrittura di oggetti. Come? Scrivendo su ogni riga i campi dell'istanza e separando gli stessi con un carattere delimitatore. Ogni riga è dunque un record per l'oggetto! Il carattere "|" è il carattere delimitatore più usato, attenti però a essere certi dell'assenza di questo carattere all'interno del testo dell'oggetto! Se creo l'oggetto con:

MagicCard a=new MagicCard("Kithkin Araldo",1,3,2);

si dovrà allora scrivere nel file:

Kithkin Araldo|1|3|2

Chi scriverà l'output su file in quel modo?
Nessuno. Alla classe va quindi aggiunto un metodo che lo fa. Se abbiamo già un oggetto PrintWriter la stampa avviene passando la stringa che descrive l'oggetto al metodo println()! La stringa da passare è ovviamente quella che descrive i campi dell'oggetto con il carattere delimitatore.

public void writeData(PrintWriter output) {
   String data=this.getName()+"|"+
   "this.getAttack()+"|"+
   this.getDefend()+"|"+
   this.getMana();
   output.println(data);
}

Prima ancora di occuparci della lettura dei record di oggetti occorre presentare una classe particolarmente utile, si chiama StringTokenizer. Il costruttore di questa classe riceve una stringa (ad esempio l'intero record letto con readLine()) e un carattere separatore. L'oggetto costruito è in grado di darci ogni singolo token della stringa passata!

StringTokenizer line=new StringTokenizer(row,"|");

L'estrazione dei token è possibile finché nell'oggetto esistono token non ancora consumati! Per sapere se nell'oggetto ci sono altri token va usato il metodo hasMoreTokens(), che ritorna un valore booleano. Con nextToken(), invece, accediamo al successivo token ancora presente nell'oggetto. Attenzione, tutti i token restituiti sono adesso delle stringhe! Se uno di questi esprime un valore numerico è allora necessaria un'adeguata operazione di parsing.
La lettura del testo avviene attraverso oggetti della classe BufferReader. Con il metodo readLine() leggiamo la singola riga del file, dunque il record con i campi dell'oggetto. E' attraverso la lettura di questi valori che possiamo ricostruire un oggetto salvato in precedenza.

public MagicCard readData(BufferedReader input) {
   String line=input.readLine()
   StringTokenizer fields=new StringTokenizer(line,"|");
   String name=fields.nextToken();
   int attack=fields.nextToken();
   int defend=fields.nextToken();
   int mana=fields.nextToken();
   MagicCard tempCard=new MagicCard(name,attack,defend,mana);
   return tempCard;
}

Salvare gli oggetti come sequenza di record potrebbe risolvere il problema della persistenza dei dati utili a un'applicazione ma ne introduce altri. Cosa fare se nel file finiscono diversi oggetti? E se un oggetto ha nei propri campi dei riferimenti ad altri oggetti? E ancora, la lettura dei record è sequenziale, l'accesso al record di un oggetto avviene leggendo prima tutti quelli che lo precedono! Con il meccanismo della serializzazione possiamo automatizzare i passaggi necessari alla scrittura e lettura di oggetti, ma di questo ci occuperemo a breve.

Nessun commento:

Posta un commento