Java - 如何使用 Scanner 获取最后一行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2660942/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:16:02  来源:igfitidea点击:

Java - How do I get last line using Scanner?

javajava.util.scanner

提问by ShrimpCrackers

        while( inStream.hasNextLine() )
        {
                ...

                lineList.add( inStream.nextLine() );
        }
        ...

lineList is an ArrayList. The code is reading everything nicely except it won't grab the last line. The last two lines in the text file end like this:

lineList 是一个 ArrayList。代码很好地阅读了所有内容,只是它不会抓住最后一行。文本文件的最后两行像这样结束:

"a sentence here..."
<a blank line here. the blank line is the last line>

I'm assuming it won't grab it since hasNextLine() is not detecting another line after this one?

我假设它不会抓住它,因为 hasNextLine() 在这之后没有检测到另一行?

What's a way to grab the last line? I thought reading until it was EOF and then catching the exception might work but there doesn't seem to be a way to do that.

有什么方法可以抢到最后一行?我认为阅读直到 EOF 然后捕获异常可能会起作用,但似乎没有办法做到这一点。

EDIT: MORE INFO

编辑:更多信息

public void readLines()
{
    lineList = new ArrayList();

    try
    {
        inStream = new Scanner( new File( fileName ) );
    }
    catch( FileNotFoundException e )
    {
        System.out.println( "Error opening the file. Try again." );
    }


    if ( inStream != null )
    {
        while( inStream.hasNextLine() )
        {
            ++originalLines;

            lineList.add( inStream.nextLine() );
        }
        inStream.close();
    }
}

There's the whole method. Anything wrong?

有全方法。哪里不对了?

EDIT: EVEN MORE INFO

编辑:更多信息

public static void main(String[] args)
{
    Scanner inStream = null;
    String test = "";

    inStream = new Scanner( test );

    while( inStream.hasNextLine() )
    {
        System.out.println( inStream.nextLine() );
    }
}

It will not pick up an empty string but it will pick up a whitespace " "

它不会拾取空字符串,但会拾取空格“”

回答by polygenelubricants

nextLine()works just fine to return the last line, even if it's blank. I suspect your problem lies elsewhere.

nextLine()即使它是空白的,也可以很好地返回最后一行。我怀疑你的问题出在别处。

String multilinetext =
    "Line1\n" +
    "Line2\n" +
    "\n" +
    "Line4\n" +
    "\n";
Scanner sc = new Scanner(multilinetext);
while (sc.hasNextLine()) {
    System.out.println("[" + sc.nextLine() + "]");
}
/* prints 
[Line1]
[Line2]
[]
[Line4]
[]
*/


It will not pick up an empty string

它不会拾取空字符串

This is the correct behavior by design. If the input is an empty string, you can't expect a Scannerto say hasNextLine()and return an empty string on nextLine(), especially since this doesn't advance the Scannerpast any character.

这是设计的正确行为。如果输入是一个空字符串,你不能期望 aScannerhasNextLine()并在 上返回一个空字符串nextLine(),特别是因为这不会推进Scanner过去任何字符。

If you think about it, if you expect a Scannerto say hasNextLine()on an empty string, and return an empty string on nextLine(), then this would result in an infinite loop: it will alwayshasNextLine()and it will alwaysreturn an empty string on nextLine()forever. Such behavior is clearly impractical.

如果您考虑一下,如果您希望 a在空字符串上ScannerhasNextLine(),并在 on 上返回一个空字符串nextLine(),那么这将导致无限循环:它将始终hasNextLine()并且将始终nextLine()ever上返回空字符串。这种行为显然是不切实际的。

回答by Michael Mrozek

That code works fine for me -- are you sure there's actually a blank line at the end (as in, the file ends in two newlines, not just one)?

那个代码对我来说很好用——你确定最后有一个空行(比如,文件以两个换行符结尾,而不仅仅是一个)?

回答by Philip Tinney

Scanner won't pick up an empty String. There isn't anything to tokenize. Scanner is a tokenizer, defaulted to use Character.isWhitespace according to the Java 6 javadoc. Every time the token is encountered everything before it is returned as a string, but not including the token. If the last item is the token, it is removed and no new line is added. You might end up with empty strings in your ArrayList, but it is only an empty string, because the token has been removed. No data and no token and scanner doesn't see a line. What you are seeing in your editor isn't a blank line. Your cursor is at the point a character will be added if you type. If you don't type anything there isn't an actual line there.

扫描仪不会拾取空字符串。没有什么可以标记的。Scanner 是一个标记器,根据 Java 6 javadoc 默认使用 Character.isWhitespace。每次遇到令牌时,它都会以字符串形式返回之前的所有内容,但不包括令牌。如果最后一项是令牌,则将其删除并且不添加新行。您可能会在 ArrayList 中得到空字符串,但它只是一个空字符串,因为令牌已被删除。没有数据,也没有令牌,扫描仪也看不到一行。您在编辑器中看到的不是空行。如果您键入,您的光标将位于将添加字符的位置。如果您不输入任何内容,则那里没有实际的行。

回答by fairplay27

I would like to point out that both

我想指出的是

String multilinetext =
    "Line1\n" +
    "Line2\n" +
    "\n" +
    "Line4\n";

and

String multilinetext =
    "Line1\n" +
    "Line2\n" +
    "\n" +
    "Line4";

gives back exactly the same result using @polygenelubricants code that is:

使用@polygenelubricants 代码返回完全相同的结果,即:

[Line1]
[Line2]
[]
[Line4]

because Scanner doesn't give back final "newline" characters.

因为 Scanner 不会返回最终的“换行符”字符。

So if you want to get even a last "empty" line this is not the right solution and you should read every byte.

因此,如果您想获得最后一个“空”行,这不是正确的解决方案,您应该读取每个字节。

回答by Osmund Francis

Finally found a way to get all the lines! Here is the code:

终于找到了获取所有行的方法!这是代码:

public static void main(String[] args) {
    String multiLineText = "Line1\n" +
        "Line2\n" +
        "\n" +
        "Line4\n" +
        "\n" +
        "";
    Scanner scanner = new Scanner(multiLineText).useDelimiter("\r?\n");
    String line = firstLine(scanner);
    System.out.println("[" + line + "]");
    while (hasNextLine(scanner)) {
        line = nextLine(scanner);
        System.out.println("[" + line + "]");
    }
    /* prints ALL six lines */
    // [Line1]
    // [Line2]
    // []
    // [Line4]
    // []
    // []
    scanner.close();
}

private static String firstLine(Scanner scanner) {
    // Check for empty first line.
    scanner.useDelimiter("");
    if (scanner.hasNext("\n")) {
        scanner.useDelimiter("\r?\n");
        return "";
    }

    // Check for empty input.
    scanner.useDelimiter("\r?\n");
    if (scanner.hasNext()) {
        return scanner.next();
    }

    return "";
}

private static boolean hasNextLine(Scanner scanner) {
    return scanner.hasNext() || scanner.hasNextLine();
}

private static String nextLine(Scanner scanner) {
    if (scanner.hasNext()) {
        return scanner.next();
    }
    return scanner.nextLine();
}

You are welcome. (Tested JDK 1.8, JDK 11.0.2, JDK 12.0.2)

不客气。(已测试 JDK 1.8、JDK 11.0.2、JDK 12.0.2)

UPDATE: 2019-09-23 I found that even getting the first line can be a mission! I posted the updated code so live up to the claim "every line".

更新:2019-09-23 我发现即使拿到第一线也能成为任务!我发布了更新的代码,所以不辜负“每一行”的要求。