关于Java:为什么HasNeXT()false,但hasNextLine() 是真的?

Why is hasNext() False, but hasNextLine() is True?

问题

对于scanner对象,hasNextLine()方法如何返回true,而hasNext()方法如何返回false?

注:根据输入文件,hasNext()方法按预期返回结果;hasNextLine()方法似乎没有返回正确的结果。

代码

下面是我运行的代码,它创建了以下结果:

1
2
3
4
5
6
7
8
9
10
11
12
public void ScannerTest(Reader fileReaderObject){
    Scanner scannerObj = new Scanner(fileReaderObject);

    for(int i = 1; scannerObj.hasNext(); i++){
        System.out.println(i +":" + scannerObj.next());
        System.out.println("Has next line:" + scannerObj.hasNextLine());
        System.out.println("Has next:" + scannerObj.hasNext());
    }
    System.out.println();

    scannerObj.close();
}

输入文件

以下是我要传递给此扫描仪的文件的实际内容:

1
2
3
4
5
6
7
8
9
a   3   9
b   3   6
c   3   3
d   2   8
e   2   5
f   2   2
g   1   7
h   1   4
i   1   1

结果

以下是运行代码时控制台中打印内容的结尾,包括我无法理解的部分:

1
2
3
4
5
6
7
8
9
25: i
Has next line: true
Has next: true
26: 1
Has next line: true
Has next: true
27: 1
Has next line: true
Has next: false


在文件末尾有一个额外的换行符。

  • hasNextLine()检查缓冲区中是否还有另一个linePattern
  • hasNext()检查缓冲区中是否有可解析的标记,由扫描程序的分隔符分隔。

由于扫描器的分隔符是空白,而linePattern也是空白,所以缓冲区中可能有linePattern但没有可解析的标记。

通常,处理这个问题的最常见方法是在分析文本每一行中的所有令牌(如数字)之后始终调用nextLine()。当使用ScannerSystem.in读取用户的输入时,您需要这样做。要使扫描仪超过此空白分隔符,必须使用scanner.nextLine()清除行分隔符。请参见:使用scanner.nextline()。

附录:

linePattern定义为与此匹配的Pattern

1
2
3
4
5
6
7
private static final String LINE_SEPARATOR_PATTERN =
                                      "

|[

\u2028\u2029\u0085]"
;
private static final String LINE_PATTERN =".*("+LINE_SEPARATOR_PATTERN+")|.+$";

默认的令牌分隔符是Pattern

1
2
private static Pattern WHITESPACE_PATTERN = Pattern.compile(
                                           "\\p{javaWhitespace}+");


原因是hasNext()检查是否有更多的非空白字符可用。hasNextLine()检查是否有另一行文本可用。您的文本文件结尾可能有一个换行符,所以它有另一行,但没有其他非空白字符。

许多文本编辑器会自动在文件末尾添加新行(如果没有新行的话)。

换句话说,您的输入文件不是这样的(数字是行号):

1
2
3
4
5
1. a   3   9
2. b   3   6
3. c   3   3
4. d   2   8
5. e   2   5

实际上是这样的:

1
2
3
4
5
6
1. a   3   9
2. b   3   6
3. c   3   3
4. d   2   8
5. e   2   5
6.


简短回答

文件末尾有一个空行。

空行原因

如果你把你的内容保存到一个txt文件中,一些编辑器会给你的文件添加一个空的新行。

编辑器的行为是这样的,因为这是POSIX标准的一部分:

3.206 Line

A sequence of zero or more non- characters plus a terminating character.

这个主题已经在这个线程中讨论过了。

Java扫描器文档

下面是Java 8扫描器类的文档。

hasNext()

Returns true if this scanner has another token in its input.

hasNextLine()

Returns true if there is another line in the input of this scanner.

Java代码行为的原因

由于上述事实,hasNextLine()将返回true,但hasNext()找不到任何可以确认为Token的东西,因此返回false

有关更多信息,请参阅Durron597 Post。


你消费的是EDOCX1的价值(0),但是你要的是hasNext()hasNextLine()。默认情况下,next()将所有内容返回到下一个whitespace()。所以,您将遍历所有空格分隔的字符串,在每个字符串之后,您将询问关于nextLine()的问题。

i 1 1->hasNextLine()?真的。EDOCX1?1?也是如此。

1 1->hasNextLine()?真的。EDOCX1?1?也为真(仍为空白)

1->hasNextLine()?对(可能是行分隔符)。哈克斯顿?错误,不再有空白。


hasnext()和hasnextline()的基本概念是

HasnExtLe:如果此扫描仪的输入中有另一行,则返回"真"。此方法在等待输入时可能会阻塞。扫描器不会超过任何输入。

返回:如果且仅当此扫描仪有另一行输入时为真投掷:IllegalstateException-如果此扫描仪已关闭

哈萨特

如果下一个完整标记与指定模式匹配,则返回true。

完整的标记由匹配分隔符模式的输入进行前缀和后缀固定。此方法在等待输入时可能会阻塞。扫描器不会超过任何输入。

参数:模式-要扫描的模式

返回:如果且仅当此扫描程序具有另一个与指定模式匹配的令牌时为true

因为上次输入的nextline()为true,因为调用scan.nextline();返回下一个标记。重要的是要注意,扫描器返回一个空格和一个字母,因为它从最后一个标记的末尾读取,直到下一行的开头。