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
Read String line by line
提问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 ""

