为什么hasNextLine()永远不会结束?

时间:2011-04-13 17:44:45

标签: java java.util.scanner

对不起,如果这听起来太简单了。我是Java的新手。

以下是我用来检查hasNextLine()的一些简单代码。当我运行它时,我无法阻止它。我想如果你没有写任何输入并按 Enter ,你就会逃脱while循环。

有人可以向我解释hasNextLine()在这种情况下的工作原理吗?

import java.util.*;

public class StringRaw {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextLine()) {
            String str = sc.nextLine();
        }
        System.out.print("YOU'VE GOT THROUGH");
    }
}

5 个答案:

答案 0 :(得分:16)

从System.in读取时,默认情况下,您正在从键盘读取,这是一个无限输入流...它具有与用户键入的一样多的行。我认为发送EOF的控制序列可能有效,例如CTL-Z(或CTL-D?)。

看看我好的'ASCII图表...... CTL-C是ETX,CTL-D是EOT;其中任何一个都应该用于终止文本流。 CTL-Z是一个不应该工作的SUB(但它可能,因为控制在历史上是高度主观地解释的)。

答案 1 :(得分:5)

Ctrl + D 终止stdin的输入。 (Windows: Ctrl + Z )或从命令提供输入:

echo -e "abc\ndef" | java Program

答案 2 :(得分:5)

CTRL-D是UNIX / Linux的字符或字节流的结尾,CTRL-Z是Windows的字符或字节流的结尾(从Microsoft DOS的早期开始的历史工件)。

如果写入了问题代码,则空行不会退出循环,因为hasNextLine()不会评估为false。它将在输入字节流中有一个行终止符。

System.in是来自标准输入的字节流,通常是控制台。因此,结束字节流将停止循环。虽然nextLine()不会阻止等待输入,但hasNextLine()却会阻塞。按照设计,代码终止的唯一方法是使用Windows中的CTRL-Z或UNIX / Linux中的CTRL-D,它结束字节流,导致hasNextLine()不阻塞等待输入并返回布尔值false,终止while循环。

如果您希望它以空行输入终止,您可以检查非空行作为循环连续条件的一部分。下面的代码演示了如何将使用hasNextLine()和nextLine()的基本问题设计更改为在获取空行或输入字符结尾时终止的问题(即Windows中的CTRL-Z或UNIX中的CTRL-D / Linux的)。 while条件中的附加代码使用赋值运算符的一个特性,其中可以像表达式一样计算它们以返回已分配的值。由于它是String对象,因此String.equals()方法可以与评估一起使用。

其他附加代码只是添加了一些打印输出以显示正在发生的事情。

// HasNextLineEndDemo.java
import java.util.*;

public class HasNextLineEndDemo {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // this code is a bit gee-whiz
        // the assignment expression gets assigned sc.nextLine()
        // only if there is one because of the &&
        // if hasNextLine() is false, everything after the &&
        // gets ignored
        // in addition, the assignment operator itself, if
        // executed, returns, just like a method return,
        // whatever was assigned to str which, 
        // as a String object, can be tested to see if it is empty
        // using the String.equals() method
        int i = 1; // input line counter
        String str = " "; // have to seed this to other than ""
        System.out.printf("Input line %d: ", i); // prompt user
        while (sc.hasNextLine() && !(str = sc.nextLine()).equals("")) {
            System.out.printf("Line %d: ", i);
            System.out.println("'" + str + "'");
            System.out.printf("Input line %d: ", ++i);
        } // end while
        System.out.println("\nYOU'VE GOT THROUGH");
    } // end main
} // end class HasNextLineEndDemo

答案 3 :(得分:0)

根据我的理解,如果您以JDBC或任何迭代器作为结果集对象的示例,那么在这些情况下,您将获得一组有限的东西,并且每次迭代器都要检查是否已到达集合的末尾。 但是在上述情况下,他们无法知道用户输入的结束,即hasNextLine()无法知道用户何时要终止,因此它会无限进行下去。 最好的方法是将附加条件放在for循环中,以检查for循环中将来会失败的某些条件。 在上面的帖子中,@ Jim的答案说明了这一点。

实际上,不建议使用hasNextLine()作为控制台输入的循环终止符,因为它永远不会返回false。

答案 4 :(得分:0)

套接字输入流也有类似的问题。我发现的大多数解决方案仍然会阻止执行。事实证明,您可以使用InputStream.available()进行无阻塞检查。 因此,在这种情况下,以下方法应该起作用:

int x = System.in.available();
if (x!=0) {
    //Your code
}