Java를 사용하여 줄당 약 5-6GB의 큰 텍스트 파일을 읽어야합니다.
어떻게 빨리 할 수 있습니까?
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가 훨씬 나중에 처리 할 때까지 닫히지 않습니다.
for(String line = br.readLine(); line != null; line = br.readLine())
, BTW 자바 8에 당신이 할 수있는 try( Stream<String> lines = Files.lines(...) ){ for( String line : (Iterable<String>) lines::iterator ) { ... } }
증오에 어렵지 않다 어느.
이 블로그를보십시오 :
버퍼 크기를 지정하거나 기본 크기를 사용할 수 있습니다. 대부분의 경우 기본값은 충분히 큽니다.
// 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();
DataInputStream
하며 잘못된 스트림이 닫힙니다. Java Tutorial에는 아무런 문제가 없으며 이와 같이 임의의 타사 인터넷 쓰레기를 인용 할 필요가 없습니다.
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);
}
StandardCharsets.UTF_8
하고 Stream<String>
간결하게 사용 forEach()
하고 forEachOrdered()
이유가없는 한 특히 사용 하지 않는 것이 좋습니다.
forEach(this::process)
않지만 코드 블록을 람다 안에 람다로 쓰면 추악 해집니다 forEach()
.
forEachOrdered
. 순서대로 실행 하려면 필요합니다 . 파일에 수천 줄이 없으면 병렬화가 켜지지 않지만이 경우 스트림을 병렬화 할 수 없습니다.
다음은 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;
}
}
ByteArrayInputStream
문자열 리터럴 로 피드는 큰 텍스트 파일을 읽는 것과 어떤 관련이 있습니까?
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로 캐스팅합니다.
Iterable
이 코드를 구현하지 않으면 유용하지만 확실하게 추악 합니다. (Iterable<String>)
작동하려면 캐스트 (예 :)가 필요합니다 .
for(String line : (Iterable<String>) lines.skip(1)::iterator)
Stream
사용하는 기능을 Files.newBufferedReader
대신 Files.lines
반복적으로 호출 readLine()
할 때까지 null
대신 같은 구조를 사용하여 (Iterable<String>) lines::iterator
... 훨씬 더 간단 것 같다
수행 할 수있는 작업은 스캐너를 사용하여 전체 텍스트를 스캔하고 텍스트를 한 줄씩 살펴 보는 것입니다. 물론 다음을 가져와야합니다.
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는 파일 형식 텍스트입니다.
BufferedReader.readLine()
최고 성능의 방법을 요청했습니다.
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)이있을 수 있으므로 인코딩을 지정해야합니다.
Java로 파일을 읽는 10 가지 방법을 문서화하고 테스트 한 다음 테스트 파일에서 1KB에서 1GB까지 읽도록하여 서로 실행했습니다. 1GB 테스트 파일을 읽는 가장 빠른 3 가지 파일 읽기 방법은 다음과 같습니다.
성능 테스트를 실행할 때 콘솔에 아무것도 출력하지 않으므로 테스트 속도가 느려집니다. 나는 단지 원시 읽기 속도를 테스트하고 싶었다.
1) java.nio.file.Files.readAllBytes ()
Java 7, 8, 9에서 테스트되었습니다. 이것은 전체적으로 가장 빠른 방법이었습니다. 1GB 파일을 읽는 것은 1 초도 채 걸리지 않았습니다.
import java.io..File;
import java.io.IOException;
import java.nio.file.Files;
public class ReadFile_Files_ReadAllBytes {
public static void main(String [] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-1GB.txt";
File file = new File(fileName);
byte [] fileBytes = Files.readAllBytes(file.toPath());
char singleChar;
for(byte b : fileBytes) {
singleChar = (char) b;
System.out.print(singleChar);
}
}
}
2) java.nio.file.Files.lines ()
이것은 Java 8 및 9에서 성공적으로 테스트되었지만 람다 식에 대한 지원이 없기 때문에 Java 7에서는 작동하지 않습니다. 1GB 파일을 읽는 데 약 3.5 초가 걸렸으며 더 큰 파일을 읽는 경우에는 2 위를 차지했습니다.
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.stream.Stream;
public class ReadFile_Files_Lines {
public static void main(String[] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-1GB.txt";
File file = new File(fileName);
try (Stream linesStream = Files.lines(file.toPath())) {
linesStream.forEach(line -> {
System.out.println(line);
});
}
}
}
3) 버퍼 리더
Java 7, 8, 9에서 작동하도록 테스트되었습니다. 1GB 테스트 파일을 읽는 데 약 4.5 초가 걸렸습니다.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile_BufferedReader_ReadLine {
public static void main(String [] args) throws IOException {
String fileName = "c:\\temp\\sample-1GB.txt";
FileReader fileReader = new FileReader(fileName);
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line;
while((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
}
10 가지 파일 읽기 방법에 대한 전체 순위는 여기에서 확인할 수 있습니다 .
System.out.print/println()
여기 타이밍입니다 ; 또한 처음 두 경우에 파일이 메모리에 적합하다고 가정합니다.
자바 7 :
String folderPath = "C:/folderOfMyFile";
Path path = Paths.get(folderPath, "myFileName.csv"); //or any text file eg.: txt, bat, etc
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(path , charset)) {
while ((line = reader.readLine()) != null ) {
//separate all csv fields into string array
String[] lineVariables = line.split(",");
}
} catch (IOException e) {
System.err.println(e);
}
StandardCharsets.UTF_8
에서 확인 된 예외를 피하기 위해 사용Charset.forName("UTF-8")
Java 8에는을 사용하는 대신 사용할 수도 Files.lines()
있습니다. 입력 소스가 파일이 아니라 a Reader
또는 a와 같은 더 추상적 인 경우 s 메소드 를 통해 행을 스트리밍InputStream
할 수 있습니다 .BufferedReader
lines()
예를 들면 다음과 같습니다.
try (BufferedReader reader = new BufferedReader(...)) {
reader.lines().forEach(line -> processLine(line));
}
에서 processLine()
읽은 각 입력 줄 을 호출 합니다 BufferedReader
.
를 들어 파일을 읽는 자바 (8)
package com.java.java8;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
/**
* The Class ReadLargeFile.
*
* @author Ankit Sood Apr 20, 2017
*/
public class ReadLargeFile {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
try {
Stream<String> stream = Files.lines(Paths.get("C:\\Users\\System\\Desktop\\demoData.txt"));
stream.forEach(System.out::println);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
스캐너 클래스를 사용할 수 있습니다
Scanner sc=new Scanner(file);
sc.nextLine();
Scanner
것은 좋지만이 답변에는 올바르게 사용하기위한 전체 코드가 포함되어 있지 않습니다.
BufferedReader.readLine()
확실히 몇 배나 빠르지 만이 방법으로 초당 메가 바이트를 읽을 수 있습니다 . 다르게 생각하면 이유를 알려주십시오.
의 readLine()
방법 을 사용해야합니다 class BufferedReader
. 해당 클래스에서 새 오브젝트를 작성하고이 메소드를 조작하여 문자열에 저장하십시오.
이를 달성하는 명확한 방법은
예를 들면 다음과 같습니다.
dataFile.txt
현재 디렉토리에 있다면
import java.io.*;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class readByLine
{
public readByLine() throws FileNotFoundException
{
Scanner linReader = new Scanner(new File("dataFile.txt"));
while (linReader.hasNext())
{
String line = linReader.nextLine();
System.out.println(line);
}
linReader.close();
}
public static void main(String args[]) throws FileNotFoundException
{
new readByLine();
}
}
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream.forEach(System.out::println);
}
System.getProperty("os.name").equals("Linux")
==
! 와 비교하지 마십시오 .
BufferedReader br;
FileInputStream fin;
try {
fin = new FileInputStream(fileName);
br = new BufferedReader(new InputStreamReader(fin));
/*Path pathToFile = Paths.get(fileName);
br = Files.newBufferedReader(pathToFile,StandardCharsets.US_ASCII);*/
String line = br.readLine();
while (line != null) {
String[] attributes = line.split(",");
Movie movie = createMovie(attributes);
movies.add(movie);
line = br.readLine();
}
fin.close();
br.close();
} catch (FileNotFoundException e) {
System.out.println("Your Message");
} catch (IOException e) {
System.out.println("Your Message");
}
그것은 나를 위해 작동합니다. 희망도 당신을 도울 것입니다.
스트림을 사용하여보다 정확하게 수행 할 수 있습니다.
Files.lines(Paths.get("input.txt")).forEach(s -> stringBuffer.append(s);
나는 보통 독서 루틴을 간단하게한다 :
void readResource(InputStream source) throws IOException {
BufferedReader stream = null;
try {
stream = new BufferedReader(new InputStreamReader(source));
while (true) {
String line = stream.readLine();
if(line == null) {
break;
}
//process line
System.out.println(line)
}
} finally {
closeQuiet(stream);
}
}
static void closeQuiet(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ignore) {
}
}
}
이 코드를 사용할 수 있습니다 :
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class ReadTextFile {
public static void main(String[] args) throws IOException {
try {
File f = new File("src/com/data.txt");
BufferedReader b = new BufferedReader(new FileReader(f));
String readLine = "";
System.out.println("Reading file using Buffered Reader");
while ((readLine = b.readLine()) != null) {
System.out.println(readLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
org.apache.commons.io 패키지 를 사용하면 특히 Java 6 이하를 사용하는 레거시 코드에서 더 많은 성능을 제공했습니다.
Java 7에는 예외 처리가 적고 유용한 메소드가 더 나은 API가 있습니다.
LineIterator lineIterator = null;
try {
lineIterator = FileUtils.lineIterator(new File("/home/username/m.log"), "windows-1256"); // The second parameter is optionnal
while (lineIterator.hasNext()) {
String currentLine = lineIterator.next();
// Some operation
}
}
finally {
LineIterator.closeQuietly(lineIterator);
}
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
Apache Commons IO를 사용할 수도 있습니다 .
File file = new File("/home/user/file.txt");
try {
List<String> lines = FileUtils.readLines(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileUtils.readLines(file)
더 이상 사용되지 않는 방법입니다. 또한이 메소드는 IOUtils.readLines
BufferedReader 및 ArrayList를 사용하는을 호출합니다 . 이것은 라인 단위 방식이 아니며, 몇 GB를 읽는 데 실용적이지 않습니다.