Java扫描器无法“完成”读取输入

6

我一直在使用Java的Scanner类时遇到了困难。我可以很好地读取输入,但问题是当我想要输出内容时。给定多行输入,我希望在所有输入都被完全读取后只打印一行。以下是我用于读取输入的代码:

    public static void main(String[] args){
    Scanner scanner = new Scanner(System.in);   //scanner reads block of input
    while(scanner.hasNextLine()){    
        //body of loop goes here
        String s = scanner.nextLine();
        Scanner ls = new Scanner(s);   //scanner to parse a line of input
        while(ls.hasNext()){
        //body of nested loop goes here
        ls.next();
        }
    }
    System.out.println("Fin");
    }

即使已经读取了所有的输入行,程序也不会到达 System.out.println 消息。(注意消息不能放在其他地方,否则它将根据循环运行的次数输出相同次数)。我该如何解决这个问题?任何帮助将不胜感激。

1
你能在这两个 while 循环中加入一些错误检查打印语句,并告诉我哪一个出了问题吗? - Lucas
我尝试在每个循环中加入print语句,但它似乎并不是无限循环,相反,外部while循环无限等待更多的输入。 - mPierce
有人在下面找到了解决方法。 - Lucas
2
可能是如何在输入完成时终止Scanner?的重复问题。 - Basilevs
5个回答

0
在这种情况下,您正在从无限流中读取。如果扫描器的输入中有另一行,则hasNextLine()将继续返回true。由于它是一个System.in,它将继续从键盘读取,除非您终止它或告诉流停止。
最后按“ctrl+Z”,您会发现它可以工作。 编辑:您可以像这样做...
Scanner scanner = new Scanner(System.in);   //scanner reads block of input
        int BLOCK_SIZE  =3,count=1;
        while(scanner.hasNextLine()){    
            //body of loop goes here
            String s = scanner.nextLine();
            Scanner ls = new Scanner(s);   //scanner to parse a line of input
            while(ls.hasNext()){
            //body of nested loop goes here
            ls.next();
            }
            if(count++==BLOCK_SIZE)
            {
                break;
            }
        }
        System.out.println("Fin");

    }

有没有办法在程序中读取完所有输入后自动停止它的读取? - mPierce
你的程序如何知道它现在应该停止? - Shashank Kadne
它不知道,这就是问题所在。当我希望输出所有输入后,它只会一直等待另一行输入。 - mPierce
如果我有一块输入,比如三行文本,我希望在读取第三行后停止。 - mPierce

0

根据我看到的,你在外部 while 循环中使用了

scanner.hasNextLine();

方法。如果需要等待输入,此方法将被阻塞。此外,您还有

Scanner scanner = new Scanner(System.in);

语句。因此,系统将一直等待输入,因此 hasNextLine() 方法必须等待输入。

这就是为什么控制流会陷入循环并无法继续进行。

要解决这个问题,您可以首先将输入存储在字符串变量中,然后调用它的扫描器构造函数。


1
但是我应该将什么存储在字符串变量中呢?程序必须从控制台读取,如果我将输入的行保存到一个字符串中,那么程序是否仍然会等待新的输入行呢? - mPierce

0
你需要告诉程序不会再有输入了。这可以通过添加EOF字符来实现。在Linux上,可以在控制台中手动完成此操作,方法是按下Ctrl-D。我认为在Windows上可以按Ctrl-Z。如果您正在将输入从一个程序传输到另一个程序,则流将自动关闭。
例如:
cat filename | java MyJavaProgram

0

如何知道用户何时完成输入,下一个“Enter”不应表示新的输入行,而是输入结束?
您可以尝试计算行数,并在达到最大值后退出循环。或者您可以查找特定的输入,例如“提交”,以退出循环。 否则,使用scanner.hasNextLine(),程序将每个回车符视为新行,因此条件永远不会失败。


0

魔法的

Scanner scanner = new Scanner(System.in);
    while(scanner.hasNextLine()){ 

这意味着系统不会停止输入(除非您使用ctrl+d(Mac电脑)关闭输入)。

为了停止循环,建议在条件中加入更多内容而不仅仅是hasNextLine()。

例如:

Scanner scanner = new Scanner(System.in);   //scanner reads block of input
    int BLOCK_SIZE  =3,count=1;
    while(scanner.hasNextLine() && count++ <= BLOCK_SIZE){   //<- Use count here.
        //body of loop goes here
        String s = scanner.nextLine();
        Scanner ls = new Scanner(s);   //scanner to parse a line of input
        while(ls.hasNext()){
        //body of nested loop goes here
        ls.next();
        }
    }
    System.out.println("Fin");

}

这没有任何意义。布尔属性总是评估为真的意义在哪里?有些事情不对劲。我错过了什么吗? - Nate T
@NathanToulbert 你说得对,我写了这个答案已经有7年了,当时我被问问题者的现有代码所迷惑。只有在计划终止系统输入时才需要使用 hasNextLine - Mirror318

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接