IT

줄 단위로 문자열 읽기

lottoking 2020. 6. 26. 07:53
반응형

줄 단위로 문자열 읽기


너무 길지 않은 문자열이 주어지면 한 줄씩 읽는 가장 좋은 방법은 무엇입니까?

나는 네가 할 수 있다는 것을 안다.

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

또 다른 방법은 eol에서 하위 문자열을 취하는 것입니다.

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

다른 간단한 방법이 있습니까? 위의 접근 방식에는 문제가 없으며 간단하고 효율적으로 보일 수있는 것을 알고 있다면 관심이 있습니까?


splitString 메소드를 사용할 수도 있습니다 .

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

나는 이것이 제안 된 두 가지보다 조금 더 깨끗한 접근법이라고 생각합니다.


특히 효율성 각도에 관심이 있었기 때문에 약간의 테스트 클래스를 만들었습니다 (아래). 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();
    }
}


Apache Commons IOUtils사용하면 다음을 통해 멋지게 수행 할 수 있습니다

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

영리한 일을하지는 않지만 훌륭하고 컴팩트합니다. 스트림도 처리 할 수 ​​있으며 LineIterator원하는 경우 더 얻을 수도 있습니다 .


솔루션 사용 Java 8등의 기능 Stream APIMethod 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
}

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

다음을 사용할 수도 있습니다.

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

그 그렇지 않으면 작업 시도 교체 \n와 함께 \r\n.


You can use the stream api and a StringReader wrapped in a BufferedReader which got a lines() stream output in 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)
        );
    }
}

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).


Or use new try with resources clause combined with Scanner:

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

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

참고URL : https://stackoverflow.com/questions/1096621/read-string-line-by-line

반응형