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 split
method of String:
也可以使用split
String的方法:
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 LineIterator
too if you prefer.
它没有做任何聪明的事情,但它很好而且很紧凑。它也可以处理流,LineIterator
如果你愿意,你也可以得到一个。
回答by Olin Kirkland
You can also use:
您还可以使用:
String[] lines = someString.split("\n");
If that doesn't work try replacing \n
with \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 split
solution (in either incarnation) is simpler, but the Reader
implementation 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 8
features such as Stream API
and 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 ""