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

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

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

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

Другим способом было бы взять подстроку на eol:

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

Поскольку меня особенно интересовал угол эффективности, я создал небольшой тестовый класс (ниже). Результат для 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<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();
    }
}

Ответ 4

Используя Apache Commons IOUtils, вы можете сделать это с помощью

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

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

Ответ 5

Решение с использованием 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
}

Ответ 6

Начиная с Java 11 появился новый метод String.lines:

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

Использование:

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

Ответ 7

Вы можете использовать поток api и StringReader, завернутый в BufferedReader, который получил поток строк() в 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

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

Ответ 8

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

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

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

Ответ 9

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

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

Ответ 10

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

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

Ответ 11

В Android/Java это очень просто. Следуйте этому: -

Предположим,

String txt="I am Rahul Kushwaha.I am an Android Developer";

Теперь, чтобы разделить это на строку методом line.use split().Like: -

String txt_split=txt.split("\n");
System.out.println(txt_split);

OutPut: -

I
am
Rahul
Kushwaha
.
I
am
an
Android
Developer

Теперь, чтобы получить длину разделенной строки, используйте метод lenght().

int txt_length=txt_split.length();
System.out.println("text length=",txt_length);

Выход: -

text length=10

Для конкретных данных построчно. Вот так: -

String[] text_data=txt.split("\n");

System.out.println("Name :",text_data[2]);
System.out.println("Title :",text_data[3]);
System.out.println("Job :",text_data[8]);

Выход: -

Name :Rahul
Title :Kushwaha
Job :Android

Надеюсь, это поможет вам. Спасибо...