简体   繁体   English

为什么hasNext()为False,但hasNextLine()为True?

[英]Why is hasNext() False, but hasNextLine() is True?

Question

How is it that for a scanner object the hasNextLine() method returns true while the hasNext() method returns false? 对于扫描程序对象,当hasNext()方法返回false时, hasNextLine()方法返回true是怎么回事?

Note: Based on the input file, the hasNext() method is returning the result as expected; 注意:根据输入文件, hasNext()方法按预期返回结果; the hasNextLine() does not seem to be returning the correct result. hasNextLine()似乎没有返回正确的结果。

Code

Here's the code I'm running that's creating the results below: 这是我正在运行的代码,它创建了以下结果:

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

Input File 输入文件

The following is the actual content of the file that I'm passing to this scanner: 以下是我传递给此扫描器的文件的实际内容:

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

Result 结果

The following is the end of what's printed in the console when I run my code, and includes the portion I can't make sense of: 以下是我运行代码时在控制台中打印的内容的结尾,并包含我无法理解的部分:

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

You have a single extra newline at the end of your file. 在文件末尾有一个额外的换行符。

  • hasNextLine() checks to see if there is another linePattern in the buffer. hasNextLine()检查缓冲区中是否还有另一个linePattern
  • hasNext() checks to see if there is a parseable token in the buffer, as separated by the scanner's delimiter. hasNext()检查缓冲区中是否有可解析的令牌,由扫描器的分隔符分隔。

Since the scanner's delimiter is whitespace, and the linePattern is also white space, it is possible for there to be a linePattern in the buffer but no parseable tokens. 由于扫描器的分隔符是空格,并且linePattern也是空格,因此缓冲区中可能存在linePattern但没有可解析的标记。

Typically, the most common way to deal with this issue by always calling nextLine() after parsing all the tokens (eg numbers) in each line of your text. 通常,最常见的方法是在解析文本每行中的所有标记(例如数字)之后始终调用nextLine()来处理此问题。 You need to do this when using Scanner when reading a user's input too from System.in . 在从System.in读取用户输入时使用Scanner时需要执行此操作。 To advance the scanner past this whitespace delimiter, you must use scanner.nextLine() to clear the line delimiter. 要使扫描程序超过此空白分隔符,必须使用scanner.nextLine()清除行分隔符。 See: Using scanner.nextLine() 请参阅: 使用scanner.nextLine()


Appendix: 附录:

LinePattern is defined to be a Pattern that matches this: LinePattern被定义为匹配此的Pattern

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

The default token delimiter is this Pattern : 默认的标记分隔符是此Pattern

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

The reason is that hasNext() checks if there are any more non-whitespace characters available. 原因是hasNext()检查是否还有可用的非空白字符。 hasNextLine() checks to see if there is another line of text available. hasNextLine()检查是否有另一行文本可用。 Your text file probably has a newline at the end of it so it has another line but no more characters that are not whitespace. 您的文本文件可能在其末尾有一个换行符,因此它有另一行但没有更多的字符不是空格。

Many text editors automatically add a newline to the end of a file if there isn't one already. 如果没有文件编辑器,许多文本编辑器会自动在文件末尾添加换行符。

In other words, your input file is not this (the numbers are line numbers): 换句话说,您的输入文件不是这个(数字是行号):

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

It is actually this: 实际上是这样的:

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

Short answer 简短的回答

You have an empty line at the end of the file. 文件末尾有一个空行。


Reason for the empty line 空行的原因

If you take your content and save it for example into a txt file, some editors will add an empty new line to your file. 如果您将内容保存并将其保存为txt文件,则某些编辑器会在文件中添加一个空的新行。

The editors behave this way, because this is part of the POSIX standard: 编辑器的行为方式如此,因为这是POSIX标准的一部分:

3.206 Line 3.206线

A sequence of zero or more non- characters plus a terminating character. 零个或多个非字符加上终止字符的序列。

This topic has been discussed in this thread . 本主题已在此主题中讨论过该主题


Java Scanner documentation Java Scanner文档

Here is the documentation from the Java 8 Scanner class . 以下是Java 8 Scanner类的文档。

hasNext()

Returns true if this scanner has another token in its input. 如果此扫描器的输入中有另一个标记,则返回true。


hasNextLine()

Returns true if there is another line in the input of this scanner. 如果此扫描器的输入中有另一行,则返回true。


Reason for the Java code behavior Java代码行为的原因

Because of the above described facts, hasNextLine() will return true , but hasNext() cannot find anything, which it can recognize as Token and returns therefore false . 由于上面描述的事实, hasNextLine()将返回true ,但hasNext()找不到任何东西,它可以识别为Token并返回false

For additional infos see durron597 post. 有关其他信息,请参阅durron597帖子。

You are consuming the value of next() , but asking for hasNext() and hasNextLine() . 您正在使用next()的值,但要求hasNext()hasNextLine() next() , per default, returns everything to the next whitespace() . next() ,默认情况下,将所有内容返回到下一个whitespace() So you are iterating through all whitespace seperated strings, and after each of them you are asking about the nextLine() . 所以你在遍历所有空格分隔的字符串,然后在每个字符串后面询问nextLine()

i 1 1 -> hasNextLine() ? i 1 1 - > hasNextLine() True. 真正。 hasNext() ? hasNext() Also true. 也是如此。

1 1 -> hasNextLine() ? 1 1 - > hasNextLine() True. 真正。 hasNext() ? hasNext() Also true (still a whitespace left) 也是如此(仍然是一个空白)

1 -> hasNextLine() ? 1 - > hasNextLine() True (Line Seperator, probably). 真(Line Seperator,可能)。 haxNext? haxNext? False, no whitespace anymore. 错,再也没有空格了。

The Basic concept of hasNext() and hasNextLine() is hasNext()和hasNextLine()的基本概念是

hasNextLine :- Returns true if there is another line in the input of this scanner. hasNextLine : - 如果此扫描器的输入中有另一行,则返回true。 This method may block while waiting for input. 此方法可能在等待输入时阻塞。 The scanner does not advance past any input. 扫描仪不会超过任何输入。

Returns: true if and only if this scanner has another line of input Throws: IllegalStateException - if this scanner is closed 返回:当且仅当此扫描器具有另一行输入时返回 true抛出:IllegalStateException - 如果此扫描器已关闭

hasNext hasNext

Returns true if the next complete token matches the specified pattern. 如果下一个完整标记与指定模式匹配,则返回true。

A complete token is prefixed and postfixed by input that matches the delimiter pattern. 一个完整的标记是前缀,后缀是与分隔符模式匹配的输入。 This method may block while waiting for input. 此方法可能在等待输入时阻塞。 The scanner does not advance past any input. 扫描仪不会超过任何输入。

Parameters: pattern - the pattern to scan for 参数: pattern - 要扫描的模式

Returns: true if and only if this scanner has another token matching the specified pattern 返回:当且仅当此扫描程序具有与指定模式匹配的另一个标记时才返回 true

Since your last input saying true for nextLine() because A call to scan.nextLine(); 因为你的最后一个输入对于nextLine()来说是真的,因为A调用scan.nextLine(); returns the next token. 返回下一个标记。 It's important to note that the scanner returns a space and a letter, because it's reading from the end of the last token until the beginning of the next line. 重要的是要注意扫描仪返回一个空格和一个字母,因为它从最后一个标记的末尾读取,直到下一行的开头。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM