Чтение строк по строкам

Учитывая, что строка не слишком длинная, как лучше всего ее читать по строкам?

Я знаю, что вы можете сделать:

BufferedReader reader = new BufferedReader(new StringReader()); reader.readLine(); 

Другой способ – взять подстроку на eol:

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

Любые другие, возможно, более простые способы сделать это? У меня нет проблем с вышеуказанными подходами, просто интересно узнать, знает ли кто-нибудь из вас что-то, что может выглядеть проще и эффективнее?

Вы также можете использовать метод split для String:

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

Это дает вам все строки в удобном массиве.

Я не знаю о производительности раскола. Он использует регулярные выражения.

Существует также Scanner . Вы можете использовать его так же, как BufferedReader :

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

Я думаю, что это немного более чистый подход, который оба из предложенных.

Поскольку меня особенно интересовал угол эффективности, я создал небольшой тестовый class (ниже). Результат для 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 решение (в любом воплощении) проще, но реализация 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 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 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 lines = IOUtils.readLines(new StringReader(string)); 

Это не делает ничего умного, но это красиво и компактно. Он также будет обрабатывать streamи, и вы также можете получить LineIterator если хотите.

Решение с использованием функций Java 8 таких как Stream API и Method references

 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"); 

Если это не работает, попробуйте заменить \n на \r\n .

Вы можете использовать stream api и StringReader, завернутый в BufferedReader, который получил stream строк () в java 8:

 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 

Как и в readLine BufferedReader, символы новой строки не включены. Поддерживаются все типы разделителей строк (в одной и той же строке).

Или используйте новую попытку с предложением ресурсов в сочетании со Сканером:

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

Вы можете попробовать следующее регулярное выражение:

 \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 "" 

С Гуавой:

 ImmutableList lines = CharSource.wrap(str).readLines(); 
  • Простой способ повторить строку в java
  • Замените «\\» на «\» в строке в C #
  • Как передать аргументы командной строки в приложение WinForms?
  • Каков тип строковых литералов в C и C ++?
  • Разделить строку с разделителями на C
  • Как искать строку в нескольких файлах и возвращать имена файлов в Powershell?
  • Scala String vs java.lang.String - вывод типа
  • Разделить разделенные запятыми строки в столбце на отдельные строки
  • Это хорошая идея вернуть «const char *» из функции?
  • Удалить значение Null из массива String в java
  • Цвет различных частей строки RichTextBox
  • Давайте будем гением компьютера.