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

Java 如何检查扫描仪是否已关闭,java,Java,我一直在尝试写的两种方法都有问题。两者都涉及使用扫描仪读取文件,其中每一行都以逗号分隔。这些方法是我的FileIO类的一部分。除了那门课,我还有另外两门课,食物和食物清单。食物对象包含来自食物捐赠的多条信息(捐赠物品的人、捐赠原因等)。FoodArrayList类的功能与ArrayList几乎相同,只是我创建它只是为了存储食物对象 我正在努力解决的两种方法如下: 读取文件,并简单地计算文件中的行数。它返回行数。此方法用于确定FoodArray列表的大小。这是因为文件的每一行都描述了一个食物对象

我一直在尝试写的两种方法都有问题。两者都涉及使用扫描仪读取文件,其中每一行都以逗号分隔。这些方法是我的FileIO类的一部分。除了那门课,我还有另外两门课,食物和食物清单。食物对象包含来自食物捐赠的多条信息(捐赠物品的人、捐赠原因等)。FoodArrayList类的功能与ArrayList几乎相同,只是我创建它只是为了存储食物对象

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

  • 读取文件,并简单地计算文件中的行数。它返回行数。此方法用于确定FoodArray列表的大小。这是因为文件的每一行都描述了一个食物对象
  • 读入文件并将信息存储到FoodAryList对象中。请记住,每个逗号分隔线都描述了一个食物对象。因此,此方法遍历文件,创建食物对象,并将它们插入到FoodArray列表中,直到到达文件末尾
  • 我正在挣扎的是,我用这两种方法关闭了扫描仪。我一直在努力研究如何编写
    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();
        }
    
    但这似乎不起作用。如果我先使用方法1,然后再尝试使用方法2(请记住,我在每个方法结束时关闭了扫描仪),则跳过
    If
    语句,
    scan
    将永远不会重新实例化,并向我抛出
    非法状态异常

    我应该在前面提到的一个要点是:我希望这两种方法都是可重用的。如果方法#1一直持续到文件结束,而我稍后使用方法#2,我希望Scanner对象再次从文件开始读取。看起来唯一的方法就是重新实例化扫描器对象

    当我第一次了解Java中的I/O时,我记得有人告诉我,在使用完扫描仪对象后,一定要关闭它们。这几乎是我脑子里根深蒂固的东西。不管怎样,我该如何应对呢?我的一个想法是在两种方法的末尾将
    scan
    设置为null。这有必要吗?我在StackOverflow的其他文章中读到过,这会导致我甚至不关闭扫描仪对象,而让垃圾收集器来处理它

    除此之外,我还想知道一旦扫描仪关闭,它到底会发生什么,为什么不能重新打开。我知道它与流有关,但我不知道在Java上下文中这些是什么。我试着查了一下,但没能从中得到多少理解

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

    方法#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;
    }
    
    方法#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();
    }
    
    我想把这两种方法分开。这是因为在我的客户机类中,我执行以下操作:

        FoodArrayList list;
        FileIO fio = new FileIO();
        int listSize = fio.numberOfLines();     
        list = new FoodArrayList(listSize);     
        fio.readFile(list);
    
    FileIO类的默认构造函数已经考虑了我试图读取的特定文件。当然,重载构造函数允许使用不同的文件名作为输入。在此方面的任何帮助都将不胜感激

    我希望这两种方法都是可重用的。如果方法#1一直持续到文件结束,而我稍后使用方法#2,我希望Scanner对象再次从文件开始读取。看起来唯一的方法就是重新实例化扫描器对象

    看来你已经找到答案了。您想重新实例化
    扫描仪
    对象,而不管其中一个对象可能处于何种状态,所以只要…这样做

    在方法开始时,声明并实例化
    扫描仪
    引用。您还可以使用
    try with resources
    ,这样您的
    扫描仪在运行结束时总是关闭的

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

    即使在现实中,您正在做的工作可以用相同的方法完成,但如果您坚持分别执行这些操作,那么初始化两个不同的
    扫描仪是您的最佳选择。

    如果(scan.hasNext()==false | | scan==null)
    您应该交换条件,因为如果有可能
    scan
    对象为
    null
    ,那么您应该首先检查它。此外,只有在将
    食物
    对象存储在数组中时,才需要第一种方法。但我猜您已经在使用一些集合,而不是必需的行计数。什么是FoodArray列表?当调用其构造函数并将listsize作为参数传递时,您到底想做什么?FoodArrayList是一个与ArrayList对象操作相同的类,只是它被设计为仅存储食物对象。我知道我可以使用ArrayList的一个实例,但我有创建这个特定类的理由。当我将listSize作为参数传递时,我基本上是在创建一个具有listSize大小的食物对象数组。我可以手动计算文件和代码中放入
    list=new foodaryList(24)
    的行数。然而,从我对编码行业的理解来看,我们通常希望避免硬编码,并使代码具有灵活性。这就是我创建
    numberOfLines()
    方法的原因。我遵循您所说的。但是,这两个方法是FileIO类的一部分。在我的构造函数中,我已经实例化了我的Scanner对象。也许我误解了你的观点。你是说即使使用
    if
    语句也不要重新启动扫描仪?这样,无论我如何定义FileIO类的构造函数都无关紧要,因为我希望这些方法从