How to check if the scanner is closed

I am having problems with two methods that I was trying to write. Both include using a scanner to read in a file, where each line is separated by a comma. These methods are part of my FileIO class. In addition to this class, I also have two other classes: Food and FoodArrayList. Food items contain several pieces of information from food donations (which donated items, the reason for the donation, etc.). The FoodArrayList class has the same functionality as the ArrayList, except that I created it exclusively for storing Food objects.

Two methods that I struggle with are as follows:

  • Reads in a file and just counts the number of lines in the file. It returns the number of rows. This method is used to determine the size of the FoodArrayList. This is because each line of the file describes a Food object.
  • Reads a file and stores information in the FoodArrayList object. Remember that each comma-separated line describes a Food object. Therefore, this method goes through the file, creates the food objects and inserts them into the FoodArrayList file until it reaches the end of the file.

What I'm struggling with is that I close my scanner in both methods. And I struggled with how to write an if to determine if the scanner was closed. In both methods, I have the following at the very beginning of the method:

  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(); } 

This does not seem to work. If I first use method # 1 and then try to use method # 2 (remember that I close the scanner at the end of each method), the if skipped, and the scan never recovered, and a IllegalStateException thrown to me.

A very important point that I mentioned earlier: I want both methods to be reused. If method # 1 continues to the end of the file, and later I use method # 2, I would like the Scanner object to read from the beginning of the file again. And it seems that the only way to do this is to restore the Scanner object.

When I first learned about Java I / O, I remember that I always had to make sure to close the Scanner objects when you finished using them. This is what was almost rooted in my brain. No matter how I get around this? One of my considerations was to set scan to null at the end of both of my methods. Is it even necessary? I read about other posts on StackOverflow that would lead me to not even close my Scanner object and not let the garbage collector take care of this.

In addition to all this, I also wondered what exactly happens with the Scanner, when it is closed and why it cannot be reopened. I understand that this has something to do with Streams, but I don’t know exactly what it is in the context of Java. I tried to find the class of the stream , but could not get most of the understanding from it.

Here is the code from both of my methods:

Method # 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; } 

Method # 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(); } 

I would like to separate these two methods. This is because in my client class I am doing the following:

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

The default constructor of my FileIO class already considers the specific file I'm trying to read. Of course, the overloaded constructor allows you to use a different file name as input. Any help on this would be appreciated.

+6
source share
1 answer

I want both methods to be reused. If method # 1 continues to the end of the file, and later I use method # 2, I would like the Scanner object to read from the beginning of the file again. And it seems that the only way to do this is to restore the Scanner object.

You seem to have your answer here. You want to restore the Scanner object no matter what state one of them is in, so just ... do it.

At the beginning of your methods, declare and instantiate the Scanner link. You can also use try-with-resources so that your Scanner always closed at the end of execution.

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

Even though the work you are doing can actually be done by the same method, if you insist on doing these operations separately, then it would be best for you to initialize two different Scanner .

+2
source

All Articles