Java 逐行读取字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1096621/
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-08-11 23:40:33  来源:igfitidea点击:

Read String line by line

javastring

提问by His

Given a string that isn't too long, what is the best way to read it line by line?

给定一个不太长的字符串,逐行阅读它的最佳方法是什么?

I know you can do:

我知道你可以这样做:

BufferedReader reader = new BufferedReader(new StringReader(<string>));
reader.readLine();

Another way would be to take the substring on the eol:

另一种方法是在 eol 上取子字符串:

final String eol = System.getProperty("line.separator");
output = output.substring(output.indexOf(eol + 1));

Any other maybe simpler ways of doing it? I have no problems with the above approaches, just interested to know if any of you know something that may look simpler and more efficient?

还有其他更简单的方法吗?我对上述方法没有任何问题,只是想知道你们中是否有人知道一些看起来更简单、更有效的东西?

采纳答案by ftl

You can also use the splitmethod of String:

也可以使用splitString的方法:

String[] lines = myString.split(System.getProperty("line.separator"));

This gives you all lines in a handy array.

这为您提供了一个方便的数组中的所有行。

I don't know about the performance of split. It uses regular expressions.

我不知道 split 的性能。它使用正则表达式。

回答by notnoop

There is also Scanner. You can use it just like the BufferedReader:

还有Scanner。您可以像使用它一样使用它BufferedReader

Scanner scanner = new Scanner(myString);
while (scanner.hasNextLine()) {
  String line = scanner.nextLine();
  // process the line
}
scanner.close();

I think that this is a bit cleaner approach that both of the suggested ones.

我认为这比两个建议的方法都更简洁。

回答by Brian Agnew

Using Apache Commons IOUtilsyou can do this nicely via

使用Apache Commons IOUtils,您可以通过

List<String> lines = IOUtils.readLines(new StringReader(string));

It's not doing anything clever, but it's nice and compact. It'll handle streams as well, and you can get a LineIteratortoo if you prefer.

它没有做任何聪明的事情,但它很好而且很紧凑。它也可以处理流,LineIterator如果你愿意,你也可以得到一个。

回答by Olin Kirkland

You can also use:

您还可以使用:

String[] lines = someString.split("\n");

If that doesn't work try replacing \nwith \r\n.

如果这不起作用,请尝试替换\n\r\n.

回答by Arend

Since I was especially interested in the efficiency angle, I created a little test class (below). Outcome for 5,000,000 lines:

由于我对效率角度特别感兴趣,所以我创建了一个小测试类(如下)。5,000,000 行的结果:

Comparing line breaking performance of different solutions
Testing 5000000 lines
Split (all): 14665 ms
Split (CR only): 3752 ms
Scanner: 10005
Reader: 2060

As usual, exact times may vary, but the ratio holds true however often I've run it.

像往常一样,确切的时间可能会有所不同,但无论我经常运行它,这个比例都是正确的。

Conclusion: the "simpler" and "more efficient" requirements of the OP can't be satisfied simultaneously, the splitsolution (in either incarnation) is simpler, but the Readerimplementation beats the others hands down.

结论:无法同时满足 OP 的“更简单”和“更高效”的要求,split解决方案(在任一化身中)更简单,但Reader实现却击败了其他人。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * Test class for splitting a string into lines at linebreaks
 */
public class LineBreakTest {
    /** Main method: pass in desired line count as first parameter (default = 10000). */
    public static void main(String[] args) {
        int lineCount = args.length == 0 ? 10000 : Integer.parseInt(args[0]);
        System.out.println("Comparing line breaking performance of different solutions");
        System.out.printf("Testing %d lines%n", lineCount);
        String text = createText(lineCount);
        testSplitAllPlatforms(text);
        testSplitWindowsOnly(text);
        testScanner(text);
        testReader(text);
    }

    private static void testSplitAllPlatforms(String text) {
        long start = System.currentTimeMillis();
        text.split("\n\r|\r");
        System.out.printf("Split (regexp): %d%n", System.currentTimeMillis() - start);
    }

    private static void testSplitWindowsOnly(String text) {
        long start = System.currentTimeMillis();
        text.split("\n");
        System.out.printf("Split (CR only): %d%n", System.currentTimeMillis() - start);
    }

    private static void testScanner(String text) {
        long start = System.currentTimeMillis();
        List<String> result = new ArrayList<>();
        try (Scanner scanner = new Scanner(text)) {
            while (scanner.hasNextLine()) {
                result.add(scanner.nextLine());
            }
        }
        System.out.printf("Scanner: %d%n", System.currentTimeMillis() - start);
    }

    private static void testReader(String text) {
        long start = System.currentTimeMillis();
        List<String> result = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new StringReader(text))) {
            String line = reader.readLine();
            while (line != null) {
                result.add(line);
                line = reader.readLine();
            }
        } catch (IOException exc) {
            // quit
        }
        System.out.printf("Reader: %d%n", System.currentTimeMillis() - start);
    }

    private static String createText(int lineCount) {
        StringBuilder result = new StringBuilder();
        StringBuilder lineBuilder = new StringBuilder();
        for (int i = 0; i < 20; i++) {
            lineBuilder.append("word ");
        }
        String line = lineBuilder.toString();
        for (int i = 0; i < lineCount; i++) {
            result.append(line);
            result.append("\n");
        }
        return result.toString();
    }
}

回答by ZhekaKozlov

Since Java 11, there is a new method String.lines:

从 Java 11 开始,有一个新方法String.lines

/**
 * Returns a stream of lines extracted from this string,
 * separated by line terminators.
 * ...
 */
public Stream<String> lines() { ... }

Usage:

用法:

"line1\nline2\nlines3"
    .lines()
    .forEach(System.out::println);

回答by Mārcis

Or use new try with resources clause combined with Scanner:

或者使用新的 try with resources 子句结合 Scanner:

   try (Scanner scanner = new Scanner(value)) {
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            // process the line
        }
    }

回答by masterxilo

You can use the stream api and a StringReader wrapped in a BufferedReader which got a lines() stream output in java 8:

您可以使用流 api 和包装在 BufferedReader 中的 StringReader ,它在 java 8 中获得了 lines() 流输出:

import java.util.stream.*;
import java.io.*;
class test {
    public static void main(String... a) {
        String s = "this is a \nmultiline\rstring\r\nusing different newline styles";

        new BufferedReader(new StringReader(s)).lines().forEach(
            (line) -> System.out.println("one line of the string: " + line)
        );
    }
}

Gives

one line of the string: this is a
one line of the string: multiline
one line of the string: string
one line of the string: using different newline styles

Just like in BufferedReader's readLine, the newline character(s) themselves are not included. All kinds of newline separators are supported (in the same string even).

就像在 BufferedReader 的 readLine 中一样,不包括换行符本身。支持各种换行符(甚至在同一个字符串中)。

回答by Batiaev

Solution using Java 8features such as Stream APIand Method references

使用Java 8诸如Stream API和的功能的解决方案Method references

new BufferedReader(new StringReader(myString))
        .lines().forEach(System.out::println);

or

或者

public void someMethod(String myLongString) {

    new BufferedReader(new StringReader(myLongString))
            .lines().forEach(this::parseString);
}

private void parseString(String data) {
    //do something
}

回答by Paul Vargas

You can try the following regular expression:

您可以尝试以下正则表达式:

\r?\n

Code:

代码:

String input = "\nab\n\n    \n\ncd\nef\n\n\n\n\n";
String[] lines = input.split("\r?\n", -1);
int n = 1;
for(String line : lines) {
    System.out.printf("\tLine %02d \"%s\"%n", n++, line);
}

Output:

输出:

Line 01 ""
Line 02 "ab"
Line 03 ""
Line 04 "    "
Line 05 ""
Line 06 "cd"
Line 07 "ef"
Line 08 ""
Line 09 ""
Line 10 ""
Line 11 ""
Line 12 ""