Riposizionare il cursore all'inizio del file

di il
8 risposte

Riposizionare il cursore all'inizio del file

Salve,

devo scrivere questo metodo:

int riconosciFrase(Iterator<String> frase), che prende un iteratore di parole che rappresenta
una frase e restituisce il numero di parole della frase che appartengono al dizionario
(distinguendo tra maiuscole e minuscole).

Ho fatto così:
int riconosciFrase(Iterator<String> frase) throws IOException
    {
        int countWord = 0;
        
        //Apertura del file
        BufferedReader in = null;
        
        try{           
            String s = null;
            
            while(frase.hasNext())
            {
                String temp = frase.next();
                in = new BufferedReader(new FileReader(filename));
                do{
                    s = in.readLine();
                    if(s!= null)
                    {
                        s = s.trim();
                        if(s.contains(temp))
                            countWord++;
                    }
                }while(s != null);
                in.close();
            }
        }
        finally
        {
            System.out.println("Tentativo chiusura file");
            if(in != null)
                in.close();
        }
        return countWord;
    }
Il metodo funziona. Vorrei sapere, però, come riposizionare il cursore all'inizio del file ad ogni passata del ciclo while(frase.hasNext()) senza dover ogni volta chiudere il file. Grazie

8 Risposte

  • Re: Riposizionare il cursore all'inizio del file

    davide.fruci ha scritto:


    Vorrei sapere, però, come riposizionare il cursore all'inizio del file ad ogni passata del ciclo while(frase.hasNext()) senza dover ogni volta chiudere il file.
    A meno di usare la funzionalità di mark/reset dei Reader (personalmente non mi affido a queste cose, in genere) ... dovresti ricreare un nuovo FileReader.

    Io però non ricreerei un bel nulla e non riposizionerei un bel nulla. Visto che l'iterator lo si può consumare una volta sola, io lo consumerei per inserire le stringhe in un HashSet o TreeSet. Poi leggerei il file una volta sola, se trovo la parola, incrementerei un contatore e rimuoverei la stringa dal set. Stop.
  • Re: Riposizionare il cursore all'inizio del file

    andbin ha scritto:


    personalmente non mi affido a queste cose, in genere
    Perché no? Se lo volessi usare, come dovrei fare? in.mark(..) dentro cosa andrebbe?

    andbin ha scritto:


    Io però non ricreerei un bel nulla e non riposizionerei un bel nulla. Visto che l'iterator lo si può consumare una volta sola, io lo consumerei per inserire le stringhe in un HashSet o TreeSet. Poi leggerei il file una volta sola, se trovo la parola, incrementerei un contatore e rimuoverei la stringa dal set. Stop.
    Ok, pensandoci come dici tu è più efficiente. Ho fatto così:
    int riconosciFrase(Iterator<String> frase) throws IOException
        {
            int countWord = 0;
            
            //Apertura del file
            BufferedReader in = new BufferedReader(new FileReader(filename));
            
            List<String> diz = new ArrayList<String>();
            
            try{           
                String s = null;
    
                do
                {
                    s = in.readLine();
                    if(s != null)
                    {
                        s = s.trim();
                        diz.add(s);
                    }
                }while(s != null);
                
                while(frase.hasNext())
                {
                    if(diz.contains(frase.next()))
                        countWord++;
                }
                
            }
            finally
            {
                System.out.println("Tentativo chiusura file");
                if(in != null)
                    in.close();
            }
            return countWord;
        }

    andbin ha scritto:


    in un HashSet o TreeSet
    Io ho utilizzato un ArrayList, che differenza c'è?

    So che nelle collezioni di tipo Set, gli oggetti non hanno un ordine. Però sono organizzati in modo da renderne la reperibilità più efficiente.

    Praticamente, ogni oggetto ha un proprio numero intero identificativo univoco. Tutti questi numeri si trovano all'interno di un HashTable che si presenta come una lista linkata.
    Mentre, i TreeSet sono un'estensione degli HashSet con in più l'ordinamento.

    Così mi pare di aver capito. Ma non riesco a vedereil vantaggio nell'usare i TreeSet rispetto agli ArrayList.
  • Re: Riposizionare il cursore all'inizio del file

    davide.fruci ha scritto:


    Perché no?
    Innanzitutto il concetto di mark/reset può essere supportato oppure no. C'è markSupported() che lo indica. E FileReader deliberatamente NON lo supporta (basta guardare i sorgenti del JDK o fare una prova veloce). Neanche FileInputStream, per la cronaca.

    CharArrayReader ad esempio lo supporta ... ma perché trattando un char[] è abbastanza banale/ovvio come si possa riportare indietro la posizione! Anche BufferedReader lo supporta, perché dentro ha un buffer.

    Comunque, a parte queste spiegazioni, potrei anche spiegarti il concetto di mark/reset ma onestamente ti sconsiglio di usarlo.

    davide.fruci ha scritto:


            List<String> diz = new ArrayList<String>();
            
            try{           
                String s = null;
    
                do
                {
                    s = in.readLine();
                    if(s != null)
                    {
                        s = s.trim();
                        diz.add(s);
                    }
                }while(s != null);
                
                while(frase.hasNext())
                {
                    if(diz.contains(frase.next()))
                        countWord++;
                }
    

    andbin ha scritto:


    in un HashSet o TreeSet
    Io ho utilizzato un ArrayList, che differenza c'è?
    Il problema è che cercare in un List (con contains o indexOf) vuol dire dover fare una ricerca "lineare", dall'inizio, fino alla fine o fino a quando si trova l'elemento.

    Ora .... supponendo come esempio una frase di 10 parole e un dizionario di 1000 parole, per ogni parola nella frase devi cercare potenzialmente nelle 1000 parole del dizionario!
    Non è proprio quello che si può definire "efficiente" ...

    davide.fruci ha scritto:


    So che nelle collezioni di tipo Set, gli oggetti non hanno un ordine.
    Set in generale non prescrive alcun criterio di ordine .... alcune implementazioni però possono definirlo e garantirlo!
    TreeSet è una collezione "sorted" e quindi è anche "ordered".

    Ok, ora chiarisco anche questi due termini:
    Una collezione è "ordered" se l'iterazione è in un ordine prevedibile. Tutte le List sono ordererd. HashMap/HashSet ad esempio no.
    Una collezione è "sorted" se gli elementi sono tenuti, e mantenuti nel tempo, già ordinati all'interno della collezione basandosi sul contenuto degli oggetti. È il caso di TreeMap (per le chiavi) e TreeSet.

    davide.fruci ha scritto:


    Però sono organizzati in modo da renderne la reperibilità più efficiente.
    Sì, o si basano su hash-table (es. HashSet) o su un albero (es. TreeSet), che sono approcci più veloci di una ricerca "lineare".

    davide.fruci ha scritto:


    Praticamente, ogni oggetto ha un proprio numero intero identificativo univoco.
    Univoco no .... Tutti gli oggetti hanno il hashCode(). Questo è il dato usato nelle collezioni basate su hash-table! Ma in generale il valore non è appunto univoco, due oggetti dello stesso tipo ma con contenuto differente, possono avere lo stesso hashCode.

    davide.fruci ha scritto:


    Tutti questi numeri si trovano all'interno di un HashTable che si presenta come una lista linkata.
    Ehm ... per dirlo meglio: una hash-table è fatta innanzitutto da un array, dove ogni elemento rappresenta un bucket ("secchio") che contiene tutti gli elementi con le stesse affinità. Il concetto di affinità è dato proprio dal hashCode e per indirizzare nell'array dei bucket si usa un certo calcolo (quale, dipende dalla implementazione) che prende in input il hashCode.

    Dietro ogni elemento nell'array ci può essere un lista linkata, dove ad esempio per HashMap contiene le entry chiave/valore. Dico "ci può essere", perché se la implementazione è "furba" usa dei reference nell'array, che possono quindi essere null (=nessuna lista) se nessun oggetto "cade" in quel bucket.

    davide.fruci ha scritto:


    Mentre, i TreeSet sono un'estensione degli HashSet con in più l'ordinamento.
    TreeSet NON è una "estensione" (se intendi nel senso della ereditarietà) di HashSet.

    davide.fruci ha scritto:


    Ma non riesco a vedereil vantaggio nell'usare i TreeSet rispetto agli ArrayList.
    Non hai più una ricerca "lineare" .... ma una ben più veloce.
  • Re: Riposizionare il cursore all'inizio del file

    Ti ringrazio per la spiegazione e per le correzioni.

    andbin ha scritto:


    Comunque, a parte queste spiegazioni, potrei anche spiegarti il concetto di mark/reset ma onestamente ti sconsiglio di usarlo.
    Se ne hai voglia sì, per favore. È sempre una conoscenza in più

    andbin ha scritto:


    Una collezione è "sorted" se gli elementi sono tenuti, e mantenuti nel tempo, già ordinati all'interno della collezione basandosi sul contenuto degli oggetti.
    Qual è il criterio per il quale siano mantenuti ordinati? Ti riferisci sempre alla struttura dell'albero binario?
  • Re: Riposizionare il cursore all'inizio del file

    davide.fruci ha scritto:


    Se ne hai voglia sì, per favore. È sempre una conoscenza in più
    Ammesso che mark/reset sia supportato e non ci siano altre questioni, l'unica cosa che devi comprendere è cosa passare a mark. Esso riceve un int di "read limit", è il numero di byte (per gli InputStream) o di caratteri (per i Reader) che si può andare avanti a leggere da quel punto, preservando il mark. Superato quel tot di byte/caratteri, il mark non è più valido, ovvero non si può tornare indietro.

    andbin ha scritto:


    Qual è il criterio per il quale siano mantenuti ordinati? Ti riferisci sempre alla struttura dell'albero binario?
    Per il criterio di ordinamento, non c'entra la struttura della collezione (c'entra ai fini della efficienza, ecc..., ovviamente).

    Nelle collezioni mantenute ordinate in base al contenuto degli oggetti, il criterio è dato da Comparable (implementato negli oggetti) o da un Comparator esplicito.
  • Re: Riposizionare il cursore all'inizio del file

    andbin ha scritto:


    Ammesso che mark/reset sia supportato e non ci siano altre questioni, l'unica cosa che devi comprendere è cosa passare a mark. Esso riceve un int di "read limit", è il numero di byte (per gli InputStream) o di caratteri (per i Reader) che si può andare avanti a leggere da quel punto, preservando il mark. Superato quel tot di byte/caratteri, il mark non è più valido, ovvero non si può tornare indietro.
    Ah, quindi quello che io metto tra parentesi in in.mark() non mi dice dove riposizionare il cursore ma quanto manca alla fine del file? Ho capito bene?

    Credevo bastasse mettere, per esempio, in.mark(0) per dirgli di riposizionare il cursore (sarebbe il mark, no?) all'inizio del file.

    Quindi come faccio?
    int riconosciFrase(Iterator<String> frase) throws IOException
        {
            int countWord = 0;
            
            //Apertura del file
            BufferedReader in = null;
            
            try{           
                String s = null;
                
                while(frase.hasNext())
                {
                    String temp = frase.next();
                    in.mark(/* cosa ci va? */);              <<<<-------
                    do{
                        s = in.readLine();
                        if(s!= null)
                        {
                            s = s.trim();
                            if(s.contains(temp))
                                countWord++;
                        }
                    }while(s != null);
                }
            }
            finally
            {
                System.out.println("Tentativo chiusura file");
                if(in != null)
                    in.close();
            }
            return countWord;
        }

    andbin ha scritto:


    Per il criterio di ordinamento, non c'entra la struttura della collezione (c'entra ai fini della efficienza, ecc..., ovviamente).

    Nelle collezioni mantenute ordinate in base al contenuto degli oggetti, il criterio è dato da Comparable (implementato negli oggetti) o da un Comparator esplicito.
    Ok, grazie
  • Re: Riposizionare il cursore all'inizio del file

    davide.fruci ha scritto:


    Ah, quindi quello che io metto tra parentesi in in.mark() non mi dice dove riposizionare il cursore ma quanto manca alla fine del file?
    No. Il punto di "marcatura" (quello a cui si può ritornare in seguito) è quello corrente nel momento in cui invochi mark. Il valore che passi a mark è il numero di byte/caratteri che puoi leggere mantenendo valido il mark. Se vai oltre a leggere, non lo è più e non puoi tornare indietro.

    BufferedReader supporta il mark/reset .... come fa? Beh, ha un buffer. Per default è grande 8192 caratteri ma se ad un certo punto invochi mark(1000000), quello che fa è semplicemente allocare un array di 1 milione di caratteri. Così tu potrai leggere fino a 1 milione di caratteri sapendo che puoi tornare indietro a quel punto del mark. Se leggi oltre, per forza di cose dovrà sovrascrivere qualcosa nel buffer ... pertanto non potrai tornare indietro.

    davide.fruci ha scritto:


    Quindi come faccio?
    Se vuoi usare il mark/reset, dovresti "sparare" un numero abbastanza alto da passare a mark che sia certamente in grado di tenere tutto il file .... non è il massimo.

    Come ho detto all'inizio, io lo risolverei opportunamente sfruttando le collezioni.
  • Re: Riposizionare il cursore all'inizio del file

    Va bene, grazie
Devi accedere o registrarti per scrivere nel forum
8 risposte