Lettura e scrittura su file

Forum di discussione sul linguaggio Java e JSP

Moderatore: Toki

Regole del forum
Leggi: IProgrammatori.it - Regolamento Forum
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Lettura e scrittura su file

Messaggioda Giuso » 13 feb 2018, 11:35

Ciao a tutti.
ho letto due esempi per capire come funziona I/O su file in java e volevo farvi qualche domanda:
Ho visto che per la lettura si utilizza un FileReader che legge un carattere finchè la read() non restituisce -1.
Analogamente per scrivere si utilizza un FileWriter con la write.
Io dovrei scrivere su file il contenuto di un arrayList ogni volta che vado a fare una modifica all'array stesso. Si tratta di un agenda di appuntamenti, salvata appunto nell'array list.
Ora mi resta da capire come fare per scrivere su file ad ogni modifica/inserimento. Se richiamo la scrittura ogni volta, non penso mi aggiorni il file ma continui a scrivere, duplicandomi le informazioni. Cè un modo per fare solo modifiche?
Avatar utente
andbin
Utente Senior
Messaggi: 3254
Iscritto il: 30 ott 2013, 21:51

Re: Lettura e scrittura su file

Messaggioda andbin » 13 feb 2018, 11:45

Giuso ha scritto:Ho visto che per la lettura si utilizza un FileReader che legge un carattere finchè la read() non restituisce -1.

Dipende ... FileReader è solo uno dei modi per leggere un file. Usare SOLO FileReader è raro o comunque meno tipico, perché con FileReader puoi solo leggere un carattere per volta o un blocco di caratteri.
Generalmente si incapsula il FileReader in altro (es. BufferedReader).

Giuso ha scritto:Analogamente per scrivere si utilizza un FileWriter con la write.

Discorso similare come per FileReader.

Giuso ha scritto:Io dovrei scrivere su file il contenuto di un arrayList ogni volta che vado a fare una modifica all'array stesso. Si tratta di un agenda di appuntamenti, salvata appunto nell'array list.
Ora mi resta da capire come fare per scrivere su file ad ogni modifica/inserimento. Se richiamo la scrittura ogni volta, non penso mi aggiorni il file ma continui a scrivere, duplicandomi le informazioni. Cè un modo per fare solo modifiche?

Qui c'è da fare un discorso in generale. Con le classi di I/O (escludiamo un momento RandomAccessFile che è particolare) come FileWriter si può solo RIscrivere il file da zero oppure "appendere" (=aggiungere) al fondo. Non puoi modificare in mezzo.
Con RandomAccessFile si può andare a modificare arbitrariamente byte in mezzo al file ma c'è comunque un limite: NON puoi "inserire" nuovi byte in un punto pensando che il resto si sposti in avanti. Non funzionano così le cose nei file-system.
Andrea, www.andbin.net — Senior Java developer — SCJP 5 (91%) – SCWCD 5 (94%)
Il mio blog sulla programmazione
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Re: Lettura e scrittura su file

Messaggioda Giuso » 13 feb 2018, 13:50

Capisco...
Se però io vado a riscrivere ogni volta che faccio una modifica mi cancella e riscrive automaticamente tutto? Se così fosse può andar bene.
Avatar utente
andbin
Utente Senior
Messaggi: 3254
Iscritto il: 30 ott 2013, 21:51

Re: Lettura e scrittura su file

Messaggioda andbin » 13 feb 2018, 13:57

Giuso ha scritto:Capisco...
Se però io vado a riscrivere ogni volta che faccio una modifica mi cancella e riscrive automaticamente tutto? Se così fosse può andar bene.

Se riscrivi il file da zero, dovrai riscrivere tutti gli elementi della tua lista. Se è appropriato/pratico oppure no dipende da quali sono i requisiti della applicazione, che dovresti valutare tu. Se è un esercizio "didattico" o qualcosa del genere, non credo ci siano problemi ma verifica ovviamente.
Andrea, www.andbin.net — Senior Java developer — SCJP 5 (91%) – SCWCD 5 (94%)
Il mio blog sulla programmazione
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Re: Lettura e scrittura su file

Messaggioda Giuso » 15 feb 2018, 11:17

Sì va bene riscriverlo da zero, cioè ad ogni modifica/inserimento richiamo il metodo che mi scrive su file e dovrei essere a posto. Il problema adesso è capire come gestire il tutto. Devo cercarmi un po' di esempi sulla scrittura di arrayList perchè non ho ancora ben capito.
Secondo te mi conviene creare una classe apposita per la gestione del file? In questo caso di che tipo dovrebbe essere per poter richiamare i metodi da un altro punto del codice (ad es. nel main)?
Avatar utente
andbin
Utente Senior
Messaggi: 3254
Iscritto il: 30 ott 2013, 21:51

Re: Lettura e scrittura su file

Messaggioda andbin » 15 feb 2018, 11:40

Giuso ha scritto:cioè ad ogni modifica/inserimento richiamo il metodo che mi scrive su file

Attenzione, non necessariamente devi riscrivere il file ad ogni singola modifica del ArrayList. Come è fatta la tua applicazione? Cioè, è una applicazione "console"? O con GUI grafica (es. Swing)? O che altro?

Gli editor di testo ad esempio non salvano certo il file ad ogni carattere che si modifica. C'è la voce "Salva" che l'utente usa. O per certi editor l'opzione abilitabile per l'auto-save ogni tot minuti. O comunque alla chiusura dell'editor se riconosce che il documento è "modificato".

Quindi nella tua applicazione: puoi offrire una opzione di "save"? O di auto-save ogni tot minuti? Oppure puoi individuare un singolo punto di uscita della applicazione per cui puoi scrivere il file in quel momento (se necessario)?

Giuso ha scritto:Il problema adesso è capire come gestire il tutto. Devo cercarmi un po' di esempi sulla scrittura di arrayList perchè non ho ancora ben capito.

A meno che usi la "serializzazione" degli oggetti (ma è da valutare MOLTO attentamente), non c'entra tanto il ArrayList in sé. La lista contiene oggetti, quali siano lo sai tu e avranno delle proprietà. Spetta a te stabilire un formato testuale o binario per rappresentare i dati.

Giuso ha scritto:Secondo te mi conviene creare una classe apposita per la gestione del file?

Assolutamente sì. In Java (e nei linguaggi ad oggetti) è sempre bene separare i concetti e fare in modo che ciascuna classe non faccia "troppe" cose.
Andrea, www.andbin.net — Senior Java developer — SCJP 5 (91%) – SCWCD 5 (94%)
Il mio blog sulla programmazione
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Re: Lettura e scrittura su file

Messaggioda Giuso » 15 feb 2018, 15:13

Console, cioè interfaccia testuale.
Non ho ben capito quella cosa degli aggiornamenti.
L'applicazione è una agenda, quindi a me basta scrivere sul file gli appuntamenti ecc. che inserisco ed eventualmente cancellare quelli che elimino(che si traduce in una riscrittura da 0 del file).
Una volta capita la scrittura, la lettura da file è analoga no?
Comunque l'ideale penso sia un formato testuale, magari di questo tipo:
Nome contatto: .......
orario appuntamento: ....
magari separando in qualche modo un appuntamento da un altro.
Avatar utente
andbin
Utente Senior
Messaggi: 3254
Iscritto il: 30 ott 2013, 21:51

Re: Lettura e scrittura su file

Messaggioda andbin » 15 feb 2018, 15:47

Giuso ha scritto:Console, cioè interfaccia testuale.

Ok

Giuso ha scritto:Non ho ben capito quella cosa degli aggiornamenti.

Facevo solo l'esempio del fatto che certi software (editor di testo, grafica o altro) hanno delle opzioni per poter salvare il documento automaticamente ogni tot minuti. Anche questa è una strategia di salvataggio.
Ma le applicazioni "console", testuali, non sono propriamente adatte ad una tale strategia. Quindi ignora quanto appena detto. ;)

Giuso ha scritto:Una volta capita la scrittura, la lettura da file è analoga no?

La scrittura del file è generalmente sempre più facile che la lettura. Perché nella lettura entrano in gioco tutta una serie di validazioni per rendere la lettura più (o meno) "robusta" possibile per riconoscere gli eventuali errore di struttura/sintassi. Detto in generale per verificare se il file è "malformato" o no.

Giuso ha scritto:Comunque l'ideale penso sia un formato testuale, magari di questo tipo:
Nome contatto: .......
orario appuntamento: ....
magari separando in qualche modo un appuntamento da un altro.

Ok ma tieni presente che la struttura di un file di dati non deve necessariamente essere davvero "parlante". Quindi ci possono essere header, prefissi, ecc.. che gli danno struttura ma senza esagerare.

Mostra la classe degli oggetti da salvare (perlomeno gli attributi), che valutiamo meglio.
Andrea, www.andbin.net — Senior Java developer — SCJP 5 (91%) – SCWCD 5 (94%)
Il mio blog sulla programmazione
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Re: Lettura e scrittura su file

Messaggioda Giuso » 15 feb 2018, 18:27

Allora, siccome posso avere appuntamenti con persone oppure semplici scadenze, posto i campi delle varie classi:

public class AppuntamentoContatto {
private String data;
private int ora;
private final String tipo;
private final String luogo;
private Contatto contatto;

public class Contatto {
public String nome;
private String cognome;
private String città;
private String eMail;
private String telNum;

public class Scadenza {
private final String scadenza;
private final int ora;
private final String descrizione;

Quindi ho un arrayList per i contatti, uno per gli appuntamenti e uno per le scadenze. Sul file mi interessa scrivere gli appuntamenti e le scadenze, tanto i contatti appaiono già nel relativo appuntamento.
Avatar utente
andbin
Utente Senior
Messaggi: 3254
Iscritto il: 30 ott 2013, 21:51

Re: Lettura e scrittura su file

Messaggioda andbin » 15 feb 2018, 18:34

Giuso ha scritto:Quindi ho un arrayList per i contatti, uno per gli appuntamenti e uno per le scadenze. Sul file mi interessa scrivere gli appuntamenti e le scadenze, tanto i contatti appaiono già nel relativo appuntamento.

La data come String mi "turba" un po' ... per l'ora più o meno nel senso che se intendi solo ore 10, ore 15 ecc... allora ok.

C'è poi un'altra questione: lo stesso identico oggetto Contatto può essere referenziato da più oggetti AppuntamentoContatto? (immagino di sì, conferma). Perché allora va mantenuta la "identità" dei contatti.
Andrea, www.andbin.net — Senior Java developer — SCJP 5 (91%) – SCWCD 5 (94%)
Il mio blog sulla programmazione
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Re: Lettura e scrittura su file

Messaggioda Giuso » 15 feb 2018, 20:38

Per quanto riguarda la data lo so che non è la scelta giusta, me pensavo fosse la cosa più semplice da fare. Ho fatto così:
int mese = Integer.parseInt(data.substring(0,2));
int giorno = Integer.parseInt(data.substring(3));
In pratica per le date controllo che la lunghezza sia 5, ovvero mese/giorno (es. 05/17), mi son dimenticato l'anno che penso che aggiungerò(il tempo stringe!).

Per l'orario metto solo un numero, facendo controlli che il numero inserito sia opportuno (se inserisco 32 ad esempio mi da errore, così come l'una del mattino).

Per i contatti: posso inserire lo stesso contatto però per un appuntamento diverso (non ho sovrapposizione di appuntamenti, ma contatti uguali è possibile).
Avatar utente
andbin
Utente Senior
Messaggi: 3254
Iscritto il: 30 ott 2013, 21:51

Re: Lettura e scrittura su file

Messaggioda andbin » 16 feb 2018, 10:54

Per la struttura del file potresti fare una cosa del genere (è solo una ipotesi, e puoi fare le varianti che vuoi):

Codice: Seleziona tutto

C:Mario|Rossi|Torino|mario@xyz.com|1234567
A:2018/03/01|15|tipo|Torino
A:2018/03/07|10|tipo|Torino
C:Roberto|Verdi|Torino|roberto@xyz.com|2345678
 ........
 ........
S:scadenza|14|descrizione


prefissi C: per i contatti; A: per gli appuntamenti; S: per le scadenze

In questo modo tutti gli appuntamenti appena dopo il contatto sono associati a quel contatto. Questo permette di mantenere la "identità" dei contatti ed avere quindi poi un solo oggetto Contatto da "distribuire" ai vari oggetti AppuntamentoContatto correlati.

Ed è tutto sommato una struttura di file abbastanza facile per il parsing e la validazione.
Andrea, www.andbin.net — Senior Java developer — SCJP 5 (91%) – SCWCD 5 (94%)
Il mio blog sulla programmazione
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Re: Lettura e scrittura su file

Messaggioda Giuso » 17 feb 2018, 12:34

Ho provato giusto per capire cosa mi buttava fuori questo metodo, e devo dire che non pensavo mi stampasse tutto alla perfezione:

public void scriviFile() throws IOException{
FileWriter writer = new FileWriter("file.txt");
int size = appsConts.size();
for (int i=0;i<size;i++) {
String str = appsConts.get(i).toString();
writer.write(str);
if(i < size-1)
writer.write("\n");
}
writer.close();
}

Questa è la sola stampa degli appuntamenti con relativo contatto e mi stampa in questo formato (che andrebbe un po' sistemato):
PERSONA: Giuseppe; Rossi; Novara; bart@gfd.it; 342154321APPUNTAMENTO: visita; 9; 12/12; centro

Ora avrei qualche domanda:
Premesso che questa scrittura su file mi va più che bene dato che ottengo ciò che è richiesto, mi chiedevo come poter modificare quel metodo per stampare in un formato un po' più leggibile, come anche tu mi avevi scritto:
Nome:.... Cognome:..... ecc.(penso non sia semplicissimo con il mio metodo fare questo).

Poi ho provato in tutti i modi a mettere uno "\n" per andare a capo sul file tra un appuntamento e l'altro, ma mi scrive tutto sulla stessa riga.

Ultima cosa, che magari vediamo dopo queste prime 2 domande :P : posso fare la lettura da file in modo analogo alla scrittura con questo metodo?
Giuso
Utente Junior
Messaggi: 28
Iscritto il: 21 dic 2017, 22:17

Re: Lettura e scrittura su file

Messaggioda Giuso » 17 feb 2018, 12:46

Premesso che questa scrittura su file mi va più che bene dato che ottengo ciò che è richiesto, mi chiedevo come poter modificare quel metodo per stampare in un formato un po' più leggibile, come anche tu mi avevi scritto:
Nome:.... Cognome:..... ecc.(penso non sia semplicissimo con il mio metodo fare questo).

Come non detto, questa parte son riuscito a farla.
Avatar utente
andbin
Utente Senior
Messaggi: 3254
Iscritto il: 30 ott 2013, 21:51

Re: Lettura e scrittura su file

Messaggioda andbin » 17 feb 2018, 14:17

Giuso ha scritto:Premesso che questa scrittura su file mi va più che bene dato che ottengo ciò che è richiesto

In realtà no, non va affatto bene! E ti dico subito perché, per almeno 2 motivi.

1) Il toString() degli oggetti AppuntamentoContatto potresti usarlo anche per altri scopi: per stampare la descrizione dell'oggetto sulla console durante la gestione o anche per altri motivi che potrebbero essere banalmente per logging e/o debugging.
Ma se usi il toString() anche per il file, il formato fornito dal toString() diventa sostanzialmente una "specifica", uno standard, che dovrai sempre rispettare. E quindi non lo potrai mai più cambiare per gli altri scopi ... a meno che vai anche a modificare la logica di lettura e parsing del file. Ma un file già scritto non lo rileggeresti.

2) Se scrivi su file gli appuntamenti così, ciascuno con il contatto referenziato, hai la ripetizione dei dati del contatto. Se inizialmente in memoria avevi 10 oggetti AppuntamentoContatto che facevano riferimento ad uno stesso oggetto Contatto, poi quando rileggi cosa ottieni? 10 oggetti Contatto DISTINTI ma con gli stessi dati? E come gestisci poi le modifiche sul contatto in modo coerente?? Diventa un pasticcio.
Te l'ho detto prima, dovresti mantenere la IDENTITÀ degli oggetti Contatto.


Giuso ha scritto:mi chiedevo come poter modificare quel metodo per stampare in un formato un po' più leggibile

Anche questo l'ho detto prima: un file di DATI non necessariamente deve essere completamente "parlante" ed intelleggibile. O forse vuoi che un utente possa usare Notepad (o altro) per editare il documento?
Più metti diciture fisse, intestazioni ecc... più diventa critico fare il parsing e le dovute validazioni sul formato. Se anche fosse molto intelleggibile da un utente "umano", se lo edita a mano con un editor e NON ha le idee chiare sul formato generale, rischia di modificare il file in modo che non sia più leggibile dalla applicazione.

Giuso ha scritto:Poi ho provato in tutti i modi a mettere uno "\n" per andare a capo sul file tra un appuntamento e l'altro, ma mi scrive tutto sulla stessa riga.

"\n" NON è la sequenza di newline su TUTTE le piattaforma. Lo è sui sistemi Unix-like ma non su Windows. Se vuoi scrivere il newline per la piattaforma su cui sta girando l'applicazione si può fare ... ma non buttando fuori "\n" e basta.

Giuso ha scritto:posso fare la lettura da file in modo analogo alla scrittura con questo metodo?

La lettura generalmente è più onerosa, richiede possibilmente validazioni più o meno "robuste" per verificare se il file è "malformato" oppure no.
E quindi dipende anche molto dal formato del file.

Ascolta quello che ti si dice .. ;)
Andrea, www.andbin.net — Senior Java developer — SCJP 5 (91%) – SCWCD 5 (94%)
Il mio blog sulla programmazione

Torna a “Java”

Chi c’è in linea

Visitano il forum: andbin, Bing [Bot] e 44 ospiti