Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it
    Registrato dal
    Apr 2014
    Messaggi
    7

    [JAVA] leggere oggetti da file txt

    Ciao a tutti, ho un problema da risolvere, devo leggere un file .txt così organizzato:
    ; Nome
    ;; 0/1
    ;;; caso a
    ;;; caso b
    ;;; caso c
    ;;; caso d
    ; Nome2
    ;; 0/1
    ;;; caso a
    ;;; caso b
    etc...


    In pratica vorrei creare un array di oggetti in cui ciascun oggetto ha tre campi:
    String Nome
    Int Numero
    String [] Casi

    i " ; " li ho messi per rendere possibile l'identificazione del tipo di riga ( ovvero a quale campo (Nome,Numero o Casi) appartiene).


    prima avevo un file organizzato così


    nome:0
    nome2:1
    nome3:0


    e operavo nel seguente modo:

    codice:
    public class Utente {    
        private String nome;
        private int scelta;
    
    
    
    
        public String getNome()
        {
            return nome;
        }
    
    
    
    
        public void setNome(String nome)
        {
            this.nome = nome;
        }
    
    
    
    
        public int getScelta()
        {
            return scelta;
        }
    
    
    
    
        public void setScelta(int scelta)
        {
            this.scelta = scelta;
        }
    
    
    
    
    }
    e nel main:

    codice:
    List<Utente> list =newArrayList<Utente>();
    
    
            File file = new File("file.txt");
            BufferedReader reader = null;
            try
            {
                reader = new BufferedReader(new FileReader(file));
                String line;
                while ((line = reader.readLine()) != null)
                {
                    String[] myString = line.split(":");
                    Utente utente = new Utente();
                    utente.setNome(myString[0]);
                    utente.setScelta(Integer.parseInt(myString[1]));
                    list.add(utente);
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            finally
            {
                if (reader != null)
                {
                    try
                    {
                        reader.close();
                    }
                    catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                }
    }
    ma ora, per problemi di spazio (dato che i "casi" possono essere molti)non posso scriverli sulla stessa riga ed effettuare un'ulteriore separazione con ad es. "::" ma ho bisogno di scriverli nel modo indicato all'inizio.Come devo modificare il codice? Grazie in anticipo

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da JavaInt Visualizza il messaggio
    ma ho bisogno di scriverli nel modo indicato all'inizio.Come devo modificare il codice?
    Ok, ora il formato di file e il codice sono chiari!

    Veniamo al problema della lettura. Il codice chiaramente lo devi modificare un po'. Non hai postato tutto il codice completo però dici che il codice per la lettura lo hai nel main. Innanzitutto ti consiglierei di incapsulare la logica di lettura in una classe apposita che si occupa solo ed esclusivamente della lettura del file (no gestione errori, no input utente, no altro).
    Magari con un metodo di istanza che legge 1 "record" (un utente) e restituisce un oggetto Utente, oppure null per indicare end-of-file (concettualmente come readLine() che restituisce la riga o null per eof).

    Il fatto che hai messo dei ';' a inizio riga per "taggare" (marcare) il tipo della riga è ovviamente buono e quindi ok. Se dopo i ';' prevedi che ci debba essere sempre uno spazio (come si vede nel tuo esempio), ancora meglio, perché rende la marcatura ancora meno equivocabile.

    Il problema quindi non è identificare il tipo della riga, questo è banale e lo risolvi con startsWith() di String. Insomma ... hai solo 3 casi possibili, basta fare 3 test.

    La cosa un pelino più problematica è la sequenza delle righe. Quando stai per leggere 1 Utente, innanzitutto leggi una riga e ti aspetti che sia quella del nome, poi leggi la riga seguente e ti aspetti che sia quella del numero. Poi fai un ciclo per leggere gli N casi.
    Il punto cruciale è qui. Ora prova a pensare: quando termina la sequenza dei casi? Semplice: quando leggi di nuovo una riga del nome.
    La questione è che la nuova riga del nome l'hai appena letta! Quindi non dovrai cercarla di nuovo. Questo vuol dire che devi salvarti da qualche parte (es. variabile di istanza) la riga che dovrai poi usare (invece che fare readLine() ) quando inizierai a leggere il successivo Utente. Questa è per così dire, la rogna principale.

    Per il resto, se fai il giusto design come ti ho suggerito all'inizio, anche tuo il main diventerà più semplice e "pulito".
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2014
    Messaggi
    7
    Innanzitutto grazie per avermi risposto.
    Per quanto riguarda la questione del main, io in realtà sto programmando in Android e quindi
    ho scritto main solo per semplicità, comunque seguirò il tuo consiglio.
    Ho scritto in questo forum perchè comunque il mio è un problema che riguarda più il linguaggio JAVA.
    Per ciò che riguarda il metodo invece, ho difficoltà ad implementare quello che mi hai suggerito.
    Scrivo uno pseudo codice per spiegarmi:


    while ((line = reader.readLine()) != null)
    {
    String myString = line;
    Utente utente = new Utente();
    if (startWith(";")){
    utente.setNome(myString);
    }
    elseif (startWith(";;")){
    utente.setScelta(Integer.parseInt(myString));
    }
    elseif (startWith(";;")){
    // qui non capisco come implementare il
    // ciclo per riempire l'array di String "Casi"
    }
    list.add(utente);
    }


    Ho 2 problemi:
    - l'oggetto deve essere aggiunto alla lista all'interno del ciclo while
    (perchè è qui che effettuo la lettura delle righe del file)
    - i casi in realtà potrebbero anche non esserci e quindi
    list.add(utente) non può essere inserito all'interno del sottociclo
    di (startWith(";;")){ ...}


    in pratica non ho capito bene cosa intendi per salvataggio in una variabile di istanza.
    Grazie ancora.

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da JavaInt Visualizza il messaggio
    Per quanto riguarda la questione del main, io in realtà sto programmando in Android
    Ok, non lo potevo sapere che si tratta di Android ma la mia indicazione di incapsulare la gestione del file in una classe a sé stante vale comunque lo stesso. Insomma è solo l'uso dei buoni principi della programmazione ad oggetti.

    Quote Originariamente inviata da JavaInt Visualizza il messaggio
    codice:
    while ((line = reader.readLine()) != null)
                {
                    String myString = line;
                    Utente utente = new Utente();
                    if (startWith(";")){
                     utente.setNome(myString);
                    }
                    elseif (startWith(";;")){
                    utente.setScelta(Integer.parseInt(myString));
                    }
                    elseif (startWith(";;")){
                    // qui non capisco come implementare il 
                    // ciclo per riempire l'array di String "Casi"
                    }                
                    list.add(utente);
                }
    Questo codice purtroppo ha parecchi problemi e "falle". Innanzitutto sei in un ciclo che legge righe continuamente (fino a eof, chiaramente). E ad ogni riga letta istanzi un oggetto Utente (ovviamente non ha senso farlo per ogni riga!). Visto che ad ogni riga hai sempre un nuovo oggetto Utente, alla riga del nome setti il nome all'oggetto Utente X e poi alla riga del numero lo setti all'oggetto Utente Y (un altro Utente). Ovviamente anche questo è sbagliato, perché non mantieni lo stesso oggetto Utente sulle N righe interessate da quel singolo utente.

    Poi comunque se non prevedi che ci sia sempre uno spazio dopo i ';', i test andrebbero fatti al contrario (prima il "marcatore" più specifico, ovvero ";;;"). Se avessi lo spazio cioè "; " / ";; " / ";;; " sarebbero inequivocabili. Se non hai lo spazio, allora testare come prima cosa solo ";" può portare ad equivoci. Se il file fosse malformato, ad esempio manca una riga del nome, tu prendi la riga del numero (che inizia comunque con un ';') e la consideri come nome. E non hai nulla nel codice che ti permette di far scoprire l'errore.

    Inoltre non fai alcun substring, quindi nome e numero li prendi con i ';' compresi (e il parseInt fallisce di certo).

    Come vedi le mancanze sono parecchie. Una lettura del genere non è difficile ma richiede un minimo di logica e ragionamento. Seguendo il mio suggerimento di incapsulare la logica in una classe a parte, si potrebbe fare (molto abbozzato!):

    codice:
    public class LettoreUtenti {
        private BufferedReader br;
        private String rigaNome;
    
        public LettoreUtenti(File file) throws ...eccezioni-necessarie... {
            // costruisci FileReader/BufferedReader
        }
    
        public void close() throws IOException {
            br.close();
        }
    
        public Utente leggiUtente() throws IOException {
            // ..... logica di lettura di 1 Utente. Ritorna null per end-of-file.
        }
    }

    Il perché ho messo la variabile di istanza 'rigaNome' l'ho spiegato nella precedente risposta.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Apr 2014
    Messaggi
    7
    si, in effetti è errato quello che ho scritto. Cercherò di basarmi su quest'ultima struttura che mi hai fornito per cercare di venirne a capo. Grazie dell'aiuto!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.