2015-12-25 11 views
6

Sto riscontrando qualche problema con due metodi che ho cercato di scrivere. Entrambi implicano l'uso di uno scanner per leggere in un file, in cui ogni riga è delimitata da virgole. I metodi fanno parte della mia classe FileIO. Oltre a quella classe, ho anche altre due classi, Food and FoodArrayList. Gli oggetti alimentari contengono diverse informazioni provenienti dalle donazioni di cibo (chi ha donato gli articoli, il motivo della donazione, ecc.). La classe FoodArrayList ha praticamente la stessa funzionalità di ArrayList, tranne per il fatto che l'ho creata esclusivamente allo scopo di memorizzare oggetti Food.Come verificare se uno scanner è stato chiuso

I due metodi che sto lottando con sono i seguenti:

  1. Legge nel file e semplicemente conta il numero di righe nel file. Restituisce il numero di linee. Questo metodo viene utilizzato per determinare la dimensione di un oggetto FoodArray. Questo perché ogni riga del file descrive un oggetto alimentare.
  2. Legge nel file e memorizza le informazioni in un oggetto FoodArrayList. Ricorda che ogni riga delimitata da una virgola descrive un oggetto Cibo. Quindi, questo metodo passa attraverso il file, crea oggetti Food e li inserisce in una FoodArrayList fino a raggiungere la fine del file.

Quello con cui sto combattendo è che chiudo il mio scanner in entrambi i metodi. E ho avuto difficoltà a scrivere un'istruzione if per rilevare se uno scanner è stato chiuso. In entrambi i metodi, ho il seguente all'inizio del metodo:

try{ 
     if(scan.hasNext() == false || scan == null) 
      scan = new Scanner(new File(this.getFileName())); 
    } 
    catch(FileNotFoundException fnfe){ 
     System.err.println("The " + fileName + " could not be found."); 
    } 
    catch(IOException ioe){ 
     ioe.printStackTrace(); 
    } 

Questo non sembra funzionare però. Se prima utilizzo il metodo n. 1 e successivamente cerco di utilizzare il metodo n. 2 (ricorda che chiudo lo scanner alla fine di ogni metodo), l'istruzione if viene saltata e scan non viene mai reintegrata e viene generato un IllegalStateException.

Un punto molto grande che avrei dovuto menzionare prima è questo: Voglio che entrambi i metodi siano riutilizzabili. Se il metodo # 1 continua fino alla fine del file e successivamente utilizzo il metodo # 2, vorrei che l'oggetto Scanner stia di nuovo leggendo dall'inizio del file. E sembra che l'unico modo per fare ciò sia di ristabilire l'oggetto Scanner.

Quando ho appreso per la prima volta di I/O in Java, ricordo che mi è stato detto di sempre assicurati di chiudere gli oggetti Scanner quando hai finito di usarli. È qualcosa che è stato radicato nel mio cervello quasi. Indipendentemente da ciò, come faccio a aggirare questo? Un pensiero che ho avuto è stato quello di impostare scan in modo null alla fine di entrambi i miei metodi. E 'anche necessario? Ho letto su altri post in StackOverflow che mi avrebbero portato a non chiudere nemmeno il mio oggetto Scanner e lasciare che il garbage collector si occupasse di esso.

Oltre a tutto questo, mi chiedevo anche cosa succede esattamente a uno scanner una volta chiuso e perché non può essere riaperto. Capisco che abbia qualcosa a che fare con gli Stream, ma non so esattamente cosa siano quelli nel contesto di Java. Ho provato a cercare lo Stream class, ma non sono riuscito a ottenere molto da esso.

Ecco il codice da entrambi i miei metodi:

Metodo # 1

public int numberOfLines(){ 
    try{ 
     if(scan.hasNext() == false || scan == null) 
      scan = new Scanner(new File(this.getFileName())); 
    } 
    catch(FileNotFoundException fnfe){ 
     System.err.println("The " + fileName + " could not be found."); 
    } 
    catch(IOException ioe){ 
     ioe.printStackTrace(); 
    } 

    int lineCount = 0; 
    while(scan.hasNextLine()){ 
     scan.nextLine(); 
     lineCount++; 
    } 
    scan.close(); 
    return lineCount; 
} 

Metodo # 2

public void readFile(FoodArrayList fal){ 
    try{ 
     if(scan.hasNext() == false || scan == null) 
      scan = new Scanner(new File(this.getFileName())); 
    } 
    catch(FileNotFoundException fnfe){ 
     System.err.println("The " + fileName + " could not be found."); 
    } 
    catch(IOException ioe){ 
     ioe.printStackTrace(); 
    } 

    while(scan.hasNextLine()){ 
     String stringRead = scan.nextLine(); 
     StringTokenizer tokens = new StringTokenizer(stringRead,","); 
     Food temp = new Food(); 
     temp.setCorpName(tokens.nextToken()); 
     temp.getContact().setLast(tokens.nextToken()); 
     temp.getContact().setFirst(tokens.nextToken()); 
     temp.setDate(tokens.nextToken()); 
     temp.setProductCode(tokens.nextToken()); 
     temp.setDescription(tokens.nextToken()); 
     temp.setReason(tokens.nextToken()); 
     String numberString = tokens.nextToken(); 
     int number = Integer.parseInt(numberString); 
     temp.setNumber(number); 
     temp.setCoP(tokens.nextToken()); 
     fal.insert((Food)temp); 
    } 
    scan.close(); 
} 

Mi piacerebbe mantenere questi due metodi separati. Questo perché nella mia classe cliente, sto effettuando le seguenti:

FoodArrayList list; 
    FileIO fio = new FileIO(); 
    int listSize = fio.numberOfLines();  
    list = new FoodArrayList(listSize);  
    fio.readFile(list); 

Il costruttore di default della mia classe FileIO considera già il file particolare sto cercando di leggere. Ovviamente, il costruttore sovraccarico consente di utilizzare un nome file diverso come input. Qualsiasi aiuto su questo sarebbe apprezzato.

+1

'if (scan.hasNext() == false || scan == null)' dovresti scambiare le condizioni, perché se esiste la possibilità che l'oggetto 'scan' sia' null', devi prima controllarlo. Inoltre, è necessario il primo metodo solo se si memorizzano gli oggetti 'Cibo' in un array. Ma suppongo che tu stia già utilizzando alcune raccolte, non il conteggio delle righe richiesto. – YoungHobbit

+0

qual è la lista di FoodArrayList? che cosa vuoi fare esattamente quando chiami il suo costruttore e passa la lista come argomento? –

+0

FoodArrayList è una classe che funziona come un oggetto ArrayList, tranne per il fatto che è progettato per memorizzare solo oggetti Food. So che avrei potuto semplicemente usare un'istanza di ArrayList, ma ho le mie ragioni per creare questa particolare classe. Quando passo listSize come argomento, in pratica sto creando una serie di oggetti Food con le dimensioni di listSize. – coolDude

risposta

2

Desidero che entrambi i metodi siano riutilizzabili. Se il metodo # 1 continua fino alla fine del file e successivamente utilizzo il metodo # 2, vorrei che l'oggetto Scanner stia di nuovo leggendo dall'inizio del file. E sembra che l'unico modo per fare ciò sia di ristabilire l'oggetto Scanner.

Sembra che tu abbia la tua risposta qui. Si desidera ripristinare l'oggetto Scanner indipendentemente dallo stato in cui si trovava uno di essi, quindi è sufficiente ... farlo.

All'inizio dei metodi, dichiarare e creare un'istanza del riferimento Scanner. Puoi anche usare try-with-resources in modo che il tuo Scanner sia sempre chiuso alla fine della sua corsa.

public void countLines() { 
    try(Scanner scan = new Scanner(new File("file.txt"))) { 
     // code 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

anche se in realtà il lavoro che stai facendo potrebbe essere realizzato con lo stesso metodo, se ti ostini a eseguire queste operazioni separatamente, quindi l'inizializzazione due differenti Scanner s è la scelta migliore.

+0

Seguo quello che stai dicendo. Tuttavia, questi due metodi fanno parte della classe FileIO. Nei miei costruttori, ho già creato un'istanza del mio oggetto Scanner. – coolDude

+0

Forse sto fraintendendo il tuo punto però. . . Stai dicendo di non usare nemmeno l'istruzione 'if' e di ripristinare lo Scanner indipendentemente? In questo modo, non importa come ho definito i miei costruttori per la classe FileIO perché vorrei che questi metodi iniziassero dall'inizio del file ogni volta che vengono utilizzati. E reintegrare gli oggetti dello scanner è l'unico modo per iniziare dall'inizio del file letto. – coolDude

+0

E voglio che il lavoro sia svolto in due metodi separati. Questo perché nella mia classe cliente, ho il seguente codice: 'elenco FoodArrayList;' ' FileIO fio = new FileIO();' ' int listSize = fio.numberOfLines();' ' list = new FoodArrayList (listSize); ' ' fio.readFile (lista); ' Tipo di difficile vedere il mio punto in un commento. Posso aggiungere questo codice alla domanda principale, se lo desideri. – coolDude

Problemi correlati