Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java에서 파일을 읽는 방법 총정리: BufferedReader, Files, Scanner 활용 가이드

Java는 파일을 읽기 위한 다양한 방법을 제공합니다. 각 방법은 상황과 파일 유형에 따라 장단점이 다르며, 어떤 방식은 대용량 파일을 읽는 데 유리하고 어떤 방식은 소용량 파일에 더 적합합니다.

이 튜토리얼에서는 Java에서 파일을 읽을 때 활용되는 다음 세 가지 클래스를 다룹니다.

  • BufferedReader
  • Files
  • Scanner

튜토리얼 전체에서는 src 디렉터리에 저장된 파일을 사용하며, 파일 경로는 src/file.txt입니다.

진행하기 전에 해당 파일에 여러 줄의 텍스트를 미리 입력해 두세요.

참고: 최선의 코딩 관행을 지키려면 이러한 구현을 사용할 때 예외 처리를 반드시 적절히 수행해야 합니다.

BufferedReader로 텍스트 파일 읽기

BufferedReader 클래스는 문자 입력 스트림을 읽는 클래스로, 기본 크기 8KB의 버퍼에 문자를 임시 저장하여 읽기 작업의 효율을 높입니다. 파일을 한 줄씩 읽어야 하는 경우라면 BufferedReader가 좋은 선택입니다.

BufferedReader는 대용량 파일을 읽을 때 특히 효율적입니다.

import java.io.*;

public class FileReaderWithBufferedReader {

    public static void main(String[] args) throws IOException {
        String file = "src/file.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));

        String curLine;
        while ((curLine = bufferedReader.readLine()) != null){
            //필요에 따라 라인을 처리합니다
            System.out.println(curLine);
        }
        bufferedReader.close();
    }
}

readLine() 메서드는 파일의 끝에 도달하면 null을 반환합니다.

참고: 파일 읽기가 끝나면 반드시 파일을 닫는 것을 잊지 마세요.

BufferedReader로 UTF-8 인코딩 파일 읽기

BufferedReader 클래스를 사용하면 UTF-8로 인코딩된 파일도 읽을 수 있습니다.

이때는 BufferedReader 인스턴스를 생성할 때 InputStreamReader 객체를 함께 전달합니다.

import java.io.*;

public class EncodedFileReaderWithBufferedReader {

    public static void main(String[] args) throws IOException {
        String file = "src/fileUtf8.txt";
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));

        String curLine;
        while ((curLine = bufferedReader.readLine()) != null){
            //필요에 따라 라인을 처리합니다
            System.out.println(curLine);
        }
    }
}

Files 클래스로 파일 읽기

Java 7의 NIO에서 도입된 Files 클래스는 파일을 다루는 정적 메서드들로만 구성되어 있습니다.

Files 클래스를 사용하면 파일의 전체 내용을 한 번에 배열로 읽어올 수 있어, 소용량 파일을 읽을 때 좋은 선택이 됩니다.

그럼 두 가지 시나리오에서 Files 클래스를 활용하는 방법을 살펴보겠습니다.

Files 클래스로 소용량 파일 읽기

Files 클래스의 readAllLines() 메서드는 파일의 전체 내용을 읽어 각 줄을 문자열 리스트에 저장합니다.

Files 클래스는 파일의 Path 객체를 인자로 받기 때문에, Path 클래스를 사용해 파일 경로를 얻을 수 있습니다.

import java.io.IOException;
import java.nio.file.*;
import java.util.*;

public class SmallFileReaderWithFiles {

    public static void main(String[] args) throws IOException {
        String file = "src/file.txt";
        Path path = Paths.get(file);
        List<String> lines = Files.readAllLines(path);
    }
}

readAllBytes()를 사용하면 파일에 저장된 데이터를 문자열 배열 대신 바이트 배열로 가져올 수 있습니다.

byte[] bytes = Files.readAllBytes(path);

Files 클래스로 대용량 파일 읽기

Files 클래스로 대용량 파일을 읽어야 한다면, newBufferedReader() 메서드로 BufferedReader 인스턴스를 얻은 뒤 한 줄씩 읽는 방식을 사용할 수 있습니다.

import java.io.*;
import java.nio.file.*;

public class LargeFileReaderWithFiles {

    public static void main(String[] args) throws IOException {
        String file = "src/file.txt";
        Path path = Paths.get(file);
        BufferedReader bufferedReader = Files.newBufferedReader(path);

        String curLine;
        while ((curLine = bufferedReader.readLine()) != null){
            System.out.println(curLine);
        }
        bufferedReader.close();
    }
}

Files.lines()로 파일 읽기

Java 8에서는 Files 클래스에 새로운 메서드가 추가되어, 파일 전체를 문자열 Stream 형태로 읽어올 수 있습니다.

import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;

public class FileReaderWithFilesLines {

    public static void main(String[] args) throws IOException {
        String file = "src/file.txt";
        Path path = Paths.get(file);
        Stream<String> lines = Files.lines(path);

        lines.forEach(s -> System.out.println(s));
        lines.close();
    }
}

Scanner로 텍스트 파일 읽기

Scanner 클래스는 지정한 구분자(delimiter)를 기준으로 파일 내용을 나눈 뒤, 부분별로 하나씩 읽어 들입니다. 이 방식은 구분자로 구분된 내용을 읽을 때 가장 적합합니다.

예를 들어 공백으로 구분된 정수 목록이나 쉼표로 구분된 문자열 목록을 읽을 때 Scanner 클래스가 이상적입니다.

Scanner 클래스의 기본 구분자는 공백(whitespace)이지만, 다른 문자나 정규 표현식으로 변경할 수도 있습니다. 또한 next(), nextInt(), nextLine(), nextByte() 등 다양한 next 계열 메서드를 통해 내용을 원하는 타입으로 변환할 수 있습니다.

import java.io.IOException;
import java.util.Scanner;
import java.io.File;

public class FileReaderWithScanner {

    public static void main(String[] args) throws IOException{
        String file = "src/file.txt";
        Scanner scanner = new Scanner(new File(file));
        scanner.useDelimiter(" ");

        while(scanner.hasNext()){
            String next = scanner.next();
            System.out.println(next);
        }
        scanner.close();
    }
}

위 예제에서는 구분자를 공백으로 설정하고, next() 메서드로 공백으로 구분된 다음 조각을 하나씩 읽어 출력합니다.

파일 전체를 한 번에 읽기

Scanner 클래스를 사용하면 반복문 없이 파일 전체를 한 번에 읽을 수도 있습니다. 이때는 구분자로 "\\Z"를 전달하면 됩니다.

scanner.useDelimiter("\\Z");
System.out.println(scanner.next());
scanner.close();
참고: Scanner 클래스는 동기화되지 않았기 때문에 스레드에 안전하지 않습니다.

마무리

이 튜토리얼에서 살펴본 것처럼, Java는 작업의 성격에 맞게 선택할 수 있는 다양한 텍스트 파일 읽기 방법을 제공합니다. 대용량 파일을 한 줄씩 읽을 때는 BufferedReader를 사용하는 것이 좋습니다.

구분자로 구분된 내용을 담은 파일을 읽을 때는 Scanner 클래스가 적합합니다.

또한 Java NIO의 Files 클래스를 활용하면 소용량 파일과 대용량 파일 모두 손쉽게 읽을 수 있습니다.