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:
- 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.
- 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.
'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
qual è la lista di FoodArrayList? che cosa vuoi fare esattamente quando chiami il suo costruttore e passa la lista come argomento? –
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