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

发布于 2024-11-01 06:35:17 字数 522 浏览 4 评论 0原文

抱歉,如果这听起来太简单了。我对 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");
    }
}

Sorry if this sounds too simple. I'm very new to Java.

Here is some simple code I was using to examine hasNextLine(). When I run it, I can't make it stop. I thought if you didn't write any input and pressed Enter, you would escape the while loop.

Can someone explain to me how hasNextLine() works in this situation?

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");
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

墟烟 2024-11-08 06:35:17

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

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

When reading from System.in, you are reading from the keyboard, by default, and that is an infinite input stream... it has as many lines as the user cares to type. I think sending the control sequence for EOF might work, such as CTL-Z (or is it CTL-D?).

Looking at my good-ol' ASCII chart... CTL-C is an ETX and CTL-D is an EOT; either of those should work to terminate a text stream. CTL-Z is a SUB which should not work (but it might, since controls are historically interpreted highly subjectively).

澜川若宁 2024-11-08 06:35:17

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

CTRL-D is the end of character or byte stream for UNIX/Linux and CTRL-Z is the end of character or byte stream for Windows (a historical artifact from the earliest days of Microsoft DOS).

With the question code as written, an empty line won't exit the loop because hasNextLine() won't evaluate to false. It will have a line terminator in the input byte stream.

System.in is a byte stream from standard input, normally the console. Ending the byte stream will therefore stop the loop. Although nextLine() doesn't block waiting for input, hasNextLine() does. The only way the code terminates, as designed, is with CTRL-Z in Windows or CTRL-D in UNIX/Linux, which ends the byte stream, causes hasNextLine() not to block waiting for input and to return a boolean false which terminates the while loop.

If you want it to terminate with an empty line input you can check for non-empty lines as part of the loop continuation condition. The following code demonstrates how to change the basic question design that uses hasNextLine() and nextLine() to one that terminates if it gets an empty line or an end of input character (i.e. CTRL-Z in Windows or CTRL-D in UNIX/Linux). The additional code in the while condition uses a feature of assignment operators wherein they can be evaluated like an expression to return the value that was assigned. Since it is a String object, the String.equals() method can be used with the evaluation.

Other additional code just adds some printed output to make what is going on obvious.

// 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
爺獨霸怡葒院 2024-11-08 06:35:17

Ctrl + D 终止来自标准输入的输入。 (Windows:Ctrl + Z)或通过命令提供输入:

echo -e "abc\ndef" | java Program

Hit Ctrl + D to terminate input from stdin. (Windows: Ctrl + Z) or provide input from a command:

echo -e "abc\ndef" | java Program
允世 2024-11-08 06:35:17

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

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

I had a similar problem with a socket input stream. Most solutions I found would still block the execution. It turns out there is a not-blocking check you can do with InputStream.available().
So in this case the following should work:

int x = System.in.available();
if (x!=0) {
    //Your code
}
药祭#氼 2024-11-08 06:35:17

根据我的理解,如果您以 JDBC 或任何迭代器的结果集对象为例,那么在这些情况下您将拥有一组有限的事物,并且迭代器每次都会检查是否已到达该集合的末尾。
然而在上面的情况下,他们无法知道用户输入的结束,即 hasNextLine() 无法知道用户何时想要终止,因此它会无限地继续下去。
最好的方法是在 for 循环上添加额外的条件,以检查 for 循环内的某些条件将来会失败。
在上面的帖子中 @Jim 的回答说明了这一点。

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

As per my understanding , if you take an example of result set object from JDBC or any iterator then in these cases you have a finite set of things and the iterators each time check whether end of the set has been reached.
However in the above case , their is no way of knowing the end of user input i.e. hasNextLine() has no way of knowing when user wants to terminate, and hence it goes on infinitely.
Best way is to put additional condition on the for loop that checks for some condition inside for loop that fails in the future.
In the above post @Jim 's answer illustrates this.

In fact using hasNextLine() as loop terminator for console input should be discouraged because it will never return false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文