문자열을 한 줄씩 읽다
너무 길지 않은 문자열이 주어진다면 한 줄씩 읽는 가장 좋은 방법은 무엇일까요?
다음을 수행할 수 있습니다.
BufferedReader reader = new BufferedReader(new StringReader(<string>));
reader.readLine();
또 다른 방법은 eol의 서브스트링을 취하는 것입니다.
final String eol = System.getProperty("line.separator");
output = output.substring(output.indexOf(eol + 1));
다른 간단한 방법은 없나요?위의 접근법에는 문제가 없습니다.단순하고 효율적으로 보일 수 있는 방법을 알고 계십니까?
도 있습니다.이 기능을 그대로 사용할 수 있습니다.BufferedReader
:
Scanner scanner = new Scanner(myString);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
// process the line
}
scanner.close();
나는 이것이 둘 다 제안하는 것보다 좀 더 깨끗한 접근법이라고 생각한다.
를 사용할 수도 있습니다.split
문자열 메서드:
String[] lines = myString.split(System.getProperty("line.separator"));
이것은 모든 라인을 편리한 배열로 제공합니다.
나는 스플릿의 퍼포먼스를 모른다.정규 표현을 사용합니다.
특히 효율 각도에 관심이 있었기 때문에, 작은 테스트 클래스(아래)를 작성했습니다.500,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 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
}
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
.
stream api와 Java 8에서 lines() 스트림 출력을 얻은 BufferedReader로 랩된 StringReader를 사용할 수 있습니다.
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과 마찬가지로 줄바꿈 문자 자체는 포함되지 않습니다.모든 종류의 줄 바꿈 구분자가 지원됩니다(같은 문자열로).
또는 Scanner와 결합된 resources 절을 사용합니다.
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 ""
가장 쉽고 보편적인 접근법은 정규식을 사용하는 것입니다.Linebreak matcher
\R
어느 쪽과 일치하는지Any Unicode linebreak sequence
:
Pattern NEWLINE = Pattern.compile("\\R")
String lines[] = NEWLINE.split(input)
@https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html 참조
언급URL : https://stackoverflow.com/questions/1096621/read-string-line-by-line
'programing' 카테고리의 다른 글
이거 보세요.컴포넌트 A의 $emit('eventName') 이벤트는 이를 트리거하지 않습니다.컴포넌트 B의 $on('eventName', callbackFunc), 핸들러를 잘못 배치했습니까? (0) | 2022.08.17 |
---|---|
C에서 nanosleep()을 사용하는 방법'tim.tv_sec'과 'tim.tv_nsec'이 뭐죠? (0) | 2022.08.17 |
C에서 true와 false 사용 (0) | 2022.08.17 |
Vuex에 디스패치된 작업 후 컴포넌트에 데이터를 전달하는 방법 (0) | 2022.08.17 |
어떻게 C의 printf의%(%)표시에서 벗어나려는 (0) | 2022.08.17 |