我不明白为什么我的java扫描程序抛出“NoSuchElementException”

时间:2016-09-30 01:17:34

标签: java

我们需要创建一个词法分析器,并且我在使用我的特定函数时遇到了一些麻烦,使用负载,或者更确切地说,在使用useLoad之后Main中会发生什么。

我发现那是因为......出于某种原因,buffer=keyboard.nextLine()正在抛出错误,因为由于某些原因它没有从键盘获得更多输入。我认为.nextLine()应该强制它从用户那里获得更多的输入。而且我不知道为什么它会在这个特定方法之后特别抛出异常。它可以做其他方法就好并且不会失去阅读能力。是因为我在另一个对象中有一个名为keyboard的变量并将其关闭吗?这似乎令人怀疑。刚刚尝试更改名称。没有什么区别。

使用但未在以下代码中声明的变量:关键字[0]是字符串“load”。 initial =传递给函数的扫描程序字符串。 offset =一个计数器变量,用于查看我们读取的行的距离。

useLoad函数(我认为这是某种方式搞乱)位于底部,但我按时间顺序包含它运行的所有内容(每个方法用水平规则分隔),以防万一我我只是没看到发生了什么。

public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in); //the scanner for keyboard
        int i = 0;
        String buffer ="";
        boolean loopControl == true;
        SymbolTable mySym = new SymbolTable();

        System.out.println("READY FOR INPUT\n");

        while (loopControl == true){
            //read in the line
            buffer = "";
            buffer = keyboard.nextLine();
            if(!mySym.checkStop(buffer)){ //if we didn't stop
                mySym.primary(buffer);
            }
            else{//if we did stop
                closeLoop();
            }

            if (i >= 55){
                loopControl = false;
                System.out.println(("You have gone over the limit ("+i+" lines) per execution. Please continue by running this program again.").toUpperCase());
                //just a safety precaution...you know... in case closeLoop doesn't work
            }
            i++;
        }


        keyboard.close();

    }
    if(initial.substring(0, Keywords[0].length()).equals(Keywords[0])){ //Load
        //if this is working as expected, then we simply need to do what the keyword says to do.
        offset += Keywords[0].length(); //we have moved this much deeper in to the line
        useLoad(offset, initial);
        offset = 0; //just make sure, once we are done with the line, we start back at the start of the next line.
        return; //we found what we were looking for, get out.
    }
private void useLoad(int offsetIn, String readIn) {
        double doubIn = 0;
        //now get the value of the 
        Scanner keyboard = new Scanner(System.in); //the scanner for keyboard
            System.out.println("\nENTER VALUE FOR " + readIn.toUpperCase());
             doubIn = keyboard.nextDouble();    
        keyboard.close();

        variables.create(readIn.substring(offsetIn), doubIn);
    }

2 个答案:

答案 0 :(得分:0)

每次循环关闭keyboard。因此,第二次从封闭的keyboard对象中读取。

快速查看Scanner.nextLine文档包含可能引发的新闻:

NoSuchElementException - if no line was found

答案 1 :(得分:0)

我想我已经找到了你的问题。

Java 7和Java 8的Java文档在Scanner的close方法文档中包含了这一行:

  

如果此扫描程序尚未关闭,那么如果其底层可读也实现Closeable接口,则将调用可读的close方法。

查看System的文档,我发现System.in的类型为InputStream,您猜对了,它实现了Closeableclose的{​​{1}}方法文档说它什么都不做;但是,InputStreamInputStreamabstract 标记为close,这意味着它可以被覆盖。 final会返回System.in,这可能会 - 并且显然 - 做一些事情。

问题是,您正在使用InputStream创建多个Scanner,并且每次关闭其中任何一个时,都会关闭System.in,使它无用!

实际上已经在另一个问题here中讨论了这个问题,并给出了解决方案。也就是说,对于你的程序,我建议采用以下两种方法之一:

  • 第一种方法在那里提到:要么使用预先制作的包装类,要么自己创建,在构造函数中接受System.in。有这个班级' InputStream实现调用其包装对象的所有方法,但{$ 1}}方法是免费销售,然后直接将InputStream传递给Scanner而不是close。但是,除非在非常具体的情况下,我会谨慎地采用这种方法,因为每当你使用其中一个包装器时,你需要在它使用结束时记住Wrapper(System.in)它的包装对象,除非它&#39 ;类似于System.in
  • 第二种方法:在程序中使用转轮类,并在那里初始化扫描仪。在构造期间将扫描仪传递到所需的对象,以便它们保持对其的引用,然后允许它们完成所需的任务而无需在类中关闭扫描程序。指定退出条件后,从那里返回到跑步者类和close扫描仪。