如何检查扫描仪是否已关闭

coo*_*ude 6 java

我在尝试编写两种方法时遇到了一些麻烦.两者都涉及使用扫描仪读取文件,其中每行以逗号分隔.这些方法是我的FileIO类的一部分.除了那个类,我还有另外两个类,Food和FoodArrayList.食品包含食品捐赠的几条信息(捐赠物品的人,捐赠的原因等).FoodArrayList类几乎具有与ArrayList相同的功能,除了我创建它只是为了存储Food对象.

我正在努力解决的两种方法如下:

  1. 读入文件并简单计算文件中的行数.它返回行数.此方法用于确定FoodArrayList的大小.这是因为文件的每一行都描述了一个Food对象.
  2. 读入文件并将信息存储到FoodArrayList对象中.请记住,每个以逗号分隔的行描述了一个Food对象.因此,此方法遍历文件,创建Food对象,并将它们插入到FoodArrayList中,直到它到达文件末尾.

我正在努力的是我在两种方法中都关闭了扫描仪.而且我一直在努力研究如何编写一个if语句来检测扫描仪是否已关闭.在这两种方法中,我在方法的最开头有以下内容:

    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();
    }
Run Code Online (Sandbox Code Playgroud)

这似乎不起作用.如果我首先使用方法#1然后再尝试使用方法#2(请记住我在每个方法结束时关闭扫描程序),该if语句将被跳过并且scan永远不会重新实例化并且我会被抛出IllegalStateException.

我之前应该提到的一个非常重要的一点是:我希望这两种方法都可以重用.如果方法#1一直持续到文件结束,我稍后再使用方法#2,我希望Scanner对象再次从文件的开头读取.似乎唯一的方法是重新实例化Scanner对象.

当我第一次了解Java中的I/O时,我记得当你完成使用它们时,总是要确保关闭Scanner对象.这几乎已经根深蒂固地融入了我的大脑.无论如何,我该如何解决这个问题?我有一个想法是scan在我的两个方法结束时设置为null.这甚至是必要的吗?我已经阅读了StackOverflow中的其他帖子,这些帖子会导致我甚至没有关闭我的Scanner对象,只是让垃圾收集器处理它.

除了所有这一切之外,我还想知道一旦扫描仪关闭后究竟发生了什么,以及为什么它不能重新打开.我知道它与Streams有关,但我不确切知道它们在Java的上下文中是什么.我尝试查找Stream类,但无法从中获得很多理解.

以下是我的两种方法的代码:

方法#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;
}
Run Code Online (Sandbox Code Playgroud)

方法#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();
}
Run Code Online (Sandbox Code Playgroud)

我想将这两种方法分开.这是因为在我的客户端类中,我执行以下操作:

    FoodArrayList list;
    FileIO fio = new FileIO();
    int listSize = fio.numberOfLines();     
    list = new FoodArrayList(listSize);     
    fio.readFile(list);
Run Code Online (Sandbox Code Playgroud)

我的FileIO类的默认构造函数已经考虑了我试图读取的特定文件.当然,重载的构造函数允许使用不同的文件名作为输入.任何有关这方面的帮助将不胜感激.

Mak*_*oto 2

我希望这两种方法都可以重复使用。如果方法 #1 一直持续到文件末尾,并且稍后我使用方法 #2,我希望 Scanner 对象再次从文件开头读取。似乎唯一的方法就是重新实例化 Scanner 对象。

看来你在这里已经有了答案。您想要重新实例化该Scanner对象,无论其中一个对象处于什么状态,所以只需...这样做。

在方法的开头,声明并实例化您的Scanner引用。您还可以使用try-with-resources这样您的程序Scanner在运行结束时始终关闭。

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

尽管实际上您正在做的工作可以用相同的方法完成,但如果您坚持单独执行这些操作,那么初始化两个不同的Scanners 是您的最佳选择。