逐行读取string
给定一个不太长的string,最好的方法是逐行读取它?
我知道你可以这样做:
BufferedReader reader = new BufferedReader(new StringReader(<string>)); reader.readLine();
另一种方法是采取在EOL的子string:
final String eol = System.getProperty("line.separator"); output = output.substring(output.indexOf(eol + 1));
任何其他更简单的方法呢? 我对上述方法没有任何问题,只是有兴趣知道是否有人知道可能看起来更简单,更有效率的东西?
你也可以使用String的split
方法:
String[] lines = myString.split(System.getProperty("line.separator"));
这给你一个方便的数组中的所有行。
我不知道分裂的performance。 它使用正则expression式。
还有Scanner
。 你可以像BufferedReader
一样使用它:
Scanner scanner = new Scanner(myString); while (scanner.hasNextLine()) { String line = scanner.nextLine(); // process the line } scanner.close();
我认为这是两个build议的一个更清洁的方法。
由于我对效率angular度特别感兴趣,所以我创build了一个小testing课(下面)。 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
像往常一样,确切的时间可能会有所不同,但是这个比例是正确的,但是我经常运行它。
结论:OP的“更简单”和“更高效”的要求不能同时满足, split
解决scheme(两种forms)都比较简单,但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(); } }
使用Apache Commons IOUtils,你可以通过很好的方式做到这一点
List<String> lines = IOUtils.readLines(new StringReader(string));
它没有做任何聪明的事情,但它很好,很紧凑。 它也会处理stream,如果你愿意,你也可以得到一个LineIterator
。
使用Java 8
function(如Stream API
和Method references
解决scheme
new BufferedReader(new StringReader(myString)) .lines().forEach(System.out::println);
要么
public void someMethod(String myLongString) { new BufferedReader(new StringReader(myLongString)) .lines().forEach(this::parseString); } private void parseString(String data) { //do something }
你也可以使用:
String[] lines = someString.split("\n");
如果这不起作用,请用\r\n
replace\r\n
。
您可以使用streamapi和一个包装在BufferedReader中的StringReader,它在java 8中获得了一个lines()stream输出:
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) ); } }
给
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
就像在BufferedReader的readLine中一样,换行符本身也不包含在内。 支持各种换行符分隔符(甚至在同一个string中)。
或者使用与Scanner结合的资源子句的新尝试:
try (Scanner scanner = new Scanner(value)) { while (scanner.hasNextLine()) { String line = scanner.nextLine(); // process the line } }
番石榴:
ImmutableList<String> lines = CharSource.wrap(str).readLines();
你可以尝试下面的正则expression式:
\r?\n
码:
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); }
输出:
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 ""