Lettura e scrittura su file

di il
17 risposte

Lettura e scrittura su file

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?

17 Risposte

  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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)?
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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).
  • Re: Lettura e scrittura su file

    Per la struttura del file potresti fare una cosa del genere (è solo una ipotesi, e puoi fare le varianti che vuoi):
    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.
  • Re: Lettura e scrittura su file

    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; ; 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 : posso fare la lettura da file in modo analogo alla scrittura con questo metodo?
  • Re: Lettura e scrittura su file

    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.
  • Re: Lettura e scrittura su file

    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 ..
Devi accedere o registrarti per scrivere nel forum
17 risposte