[java] Java를 사용하여 큰 텍스트 파일을 한 줄씩 읽는 방법은 무엇입니까?

Java를 사용하여 줄당 약 5-6GB의 큰 텍스트 파일을 읽어야합니다.

어떻게 빨리 할 수 ​​있습니까?



답변

일반적인 패턴은

try (BufferedReader br = new BufferedReader(new FileReader(file))) {
    String line;
    while ((line = br.readLine()) != null) {
       // process the line.
    }
}

문자 인코딩이 없다고 가정하면 데이터를 더 빨리 읽을 수 있습니다. 예를 들어 ASCII-7이지만 별 차이가 없습니다. 데이터 작업이 훨씬 오래 걸릴 가능성이 높습니다.

편집 : line누출 범위를 피하기 위해 덜 일반적인 패턴을 사용하십시오 .

try(BufferedReader br = new BufferedReader(new FileReader(file))) {
    for(String line; (line = br.readLine()) != null; ) {
        // process the line.
    }
    // line is not visible here.
}

업데이트 : Java 8에서는 할 수 있습니다

try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
        stream.forEach(System.out::println);
}

참고 : #close 메서드가 호출되도록 하려면 스트림을 리소스 를 사용하여 시도 블록에 배치해야합니다. 그렇지 않으면 기본 파일 핸들이 GC가 훨씬 나중에 처리 할 때까지 닫히지 않습니다.


답변

이 블로그를보십시오 :

버퍼 크기를 지정하거나 기본 크기를 사용할 수 있습니다. 대부분의 경우 기본값은 충분히 큽니다.

// Open the file
FileInputStream fstream = new FileInputStream("textfile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));

String strLine;

//Read File Line By Line
while ((strLine = br.readLine()) != null)   {
  // Print the content on the console
  System.out.println (strLine);
}

//Close the input stream
fstream.close();


답변

Java 8이 종료되면 (2014 년 3 월) 스트림을 사용할 수 있습니다.

try (Stream<String> lines = Files.lines(Paths.get(filename), Charset.defaultCharset())) {
  lines.forEachOrdered(line -> process(line));
}

파일의 모든 줄을 인쇄 :

try (Stream<String> lines = Files.lines(file, Charset.defaultCharset())) {
  lines.forEachOrdered(System.out::println);
}


답변

다음은 Java 7 이전에 대한 전체 오류 처리 및 지원 문자 세트 스펙이있는 샘플입니다. Java 7에서는 try-with-resources 구문을 사용하여 코드를 더 깨끗하게 만들 수 있습니다.

기본 문자셋 만 원하면 InputStream을 건너 뛰고 FileReader를 사용할 수 있습니다.

InputStream ins = null; // raw byte-stream
Reader r = null; // cooked reader
BufferedReader br = null; // buffered for readLine()
try {
    String s;
    ins = new FileInputStream("textfile.txt");
    r = new InputStreamReader(ins, "UTF-8"); // leave charset out for default
    br = new BufferedReader(r);
    while ((s = br.readLine()) != null) {
        System.out.println(s);
    }
}
catch (Exception e)
{
    System.err.println(e.getMessage()); // handle exception
}
finally {
    if (br != null) { try { br.close(); } catch(Throwable t) { /* ensure close happens */ } }
    if (r != null) { try { r.close(); } catch(Throwable t) { /* ensure close happens */ } }
    if (ins != null) { try { ins.close(); } catch(Throwable t) { /* ensure close happens */ } }
}

전체 오류 처리가 포함 된 Groovy 버전은 다음과 같습니다.

File f = new File("textfile.txt");
f.withReader("UTF-8") { br ->
    br.eachLine { line ->
        println line;
    }
}


답변

Java 8에서는 다음을 수행 할 수 있습니다.

try (Stream<String> lines = Files.lines (file, StandardCharsets.UTF_8))
{
    for (String line : (Iterable<String>) lines::iterator)
    {
        ;
    }
}

일부 참고 사항 : Files.lines(대부분의 스트림과 달리) 반환 된 스트림을 닫아야합니다. 여기에 언급 된 이유로 나는을 사용하지 마십시오 forEach(). 이상한 코드 (Iterable<String>) lines::iterator는 Stream을 Iterable로 캐스팅합니다.


답변

수행 할 수있는 작업은 스캐너를 사용하여 전체 텍스트를 스캔하고 텍스트를 한 줄씩 살펴 보는 것입니다. 물론 다음을 가져와야합니다.

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public static void readText throws FileNotFoundException {
    Scanner scan = new Scanner(new File("samplefilename.txt"));
    while(scan.hasNextLine()){
        String line = scan.nextLine();
        //Here you can manipulate the string the way you want
    }
}

스캐너는 기본적으로 모든 텍스트를 스캔합니다. while 루프는 전체 텍스트를 탐색하는 데 사용됩니다.

.hasNextLine()함수는 텍스트에 줄이 더 있으면 true를 반환하는 부울입니다. 이 .nextLine()함수는 전체 줄을 String으로 제공하여 원하는 방식으로 사용할 수 있습니다. System.out.println(line)텍스트를 인쇄 해보십시오 .

참고 : .txt는 파일 형식 텍스트입니다.


답변

FileReader에서 인코딩 InputStreamReader을 지정할 수 없으므로 지정해야 할 경우 대신 사용하십시오.

try {
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "Cp1252"));

    String line;
    while ((line = br.readLine()) != null) {
        // process the line.
    }
    br.close();

} catch (IOException e) {
    e.printStackTrace();
}

Windows에서이 파일을 가져온 경우 ANSI 인코딩 (Cp1252)이있을 수 있으므로 인코딩을 지정해야합니다.