[자바/심화] 파일 입출력

파일 출력

FileOutputStream

import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FileOutputStream output = new FileOutputStream("c:/out.txt");
        for(int i=1; i<11; i++) {
            // 유닉스에서는 "\n", 윈도우에서는 "\r\n"으로 줄바꿈을 표현해주면 여러 에디터에서 제대로 표현된다.
            String data = i+" 번째 줄입니다.\r\n";
            output.write(data.getBytes());
        }
        /*
            - 사용한 파일 객체를 닫아 주기 위한 코드이다.
            - 자바 프로그램을 종료할 때 사용한 파일 객체를 자동으로 닫아 주기 때문에 생략해도 된다.
              하지만, 사용했더 파일을 닫지 않고 재 사용할 때 오류가 발생하므로, 직접 닫아주는 것이 좋다.
        */
        output.close();
    }
}

- C:\와 같은 폴더의 경로를 생략하면 현재 프로그램이 실행되는 디렉터리에 해당 파일을 생성한다.

- FileOutputStream 클래스는 객체를 생성할 때 생성자의 입력으로 파일명을 넘겨주어야 한다. 

- FileOutputStream 클래스는 OutputStream 클래스를 상속받아 만든 클래스이므로 역시 byte 단위로 데이터를 처리한다.

- FileOutputStream에 데이터를 쓸 때는 byte 단위로 써야 하므로 getBytes() 메소드를 이용하여 String을 Byte로 변경해주어야 한다.

FileWriter

import java.io.FileWriter;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            fw.write(data);
        }
        fw.close();
    }
}

- FileOutputStream 대신에 FileWriter를 이용하면 byte 배열 대신 문자열을 사용할 수 있어 편리하다.

PrintWriter

import java.io.IOException;
import java.io.PrintWriter;

public class Main {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.";
            pw.println(data);
        }
        pw.close();
    }
}

- FileWrite를 이용하여 파일에 입력할 때 줄 개행을 위해 "\r\n"을 사용하는 부분을 해소하기 위해 PrintWriter를 사용하면 "\r\n"을 덧붙이는 대신 "println" 메소드를 통하여 입력할 수 있다.

파일에 내용 추가하기

import java.io.FileWriter;
import java.io.IOException;

public class Sample {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("c:/out.txt");
        for(int i=1; i<11; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            fw.write(data);
        }
        fw.close();

        FileWriter fw2 = new FileWriter("c:/out.txt", true);  // 파일을 추가 모드로 연다.
        // PrintWriter pw2 = new PrintWriter(new FileWriter("c:/out.txt", true));
        for(int i=11; i<21; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            fw2.write(data);
        }
        fw2.close();
    }
}

- FileWriter의 두 번째 boolean 입력 파라미터는 파일을 추가 모드로 열 것인지에 대한 구분 값이다.
  생략되는 경우 기본값인 false로 인식되며, true이면 파일을 추가 모드로 연다.

파일 입력

FileInputStream

import java.io.FileInputStream;
import java.io.IOException;

public class Sample {
    public static void main(String[] args) throws IOException {
        byte[] bytes = new byte[1024];
        FileInputStream input = new FileInputStream("C:/out.txt");
        input.read(bytes);
        System.out.println(new String(bytes));  // byte 배열을 문자열로 변경하여 출력
        input.close();
    }
}

- C:\와 같은 폴더의 경로를 생략하면 현재 프로그램이 실행되는 디렉터리에 있는 파일을 읽어온다. 이 때는 ./out.txt와 같이 작성하면 된다.

- byte 배열을 이용하여 파일을 읽어야 하기 때문에 읽어야 하는 데이터 길이를 아는 경우에 사용하기 적합하며, 길이를 모르는 경우에는 불편한 점이 있다.

- byte 배열을 문자열로 변경할 때는 new String(byte 배열)처럼 사용하여 변경한다.

BefferedReader

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Sample {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("c:/out.txt"));
        while(true) {
            String line = br.readLine();
            if (line==null) break;  // 더 이상 읽을 라인이 없을 경우 while 문을 빠져나간다.
            System.out.println(line);
        }
        br.close();
    }
}

- FileReader와 BufferedReader의 조합을 사용하면 한 줄 단위로 파일을 읽을 수 있다.

- BufferedReader의 readLine 메서드는 더 이상 읽을 라인이 없을 경우 null을 리턴하므로 이를 조건문을 활용하여 반복문을 중지시킬 수 있다.

예제

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("./memo.txt");
        String memo = "헤드 라인\n";
        fw.write(memo);

        memo = "1월 1일 날씨 맑음\n";
        fw.write(memo);
        fw.close();

        PrintWriter pw = new PrintWriter("./memo.txt");
        memo = "헤드 라인";
        pw.println(memo);
        memo = "1월 1일 날씨 맑음";
        pw.println(memo);
        pw.close();

        FileWriter fw2 = new FileWriter("./memo.txt", true);
        memo = "1월 2일 날씨 완전 맑음\n";
        fw2.write(memo);
        fw2.close();

        PrintWriter pw2 = new PrintWriter(new FileWriter("./memo.txt", true));
        memo = "1월 3일 날씨 또 맑음!";
        pw2.println(memo);
        pw2.close();

        BufferedReader br = new BufferedReader(new FileReader("./memo.txt"));
        while (true) {
            String line = br.readLine();
            if (line == null) {
                break;
            }
            System.out.println(line);
        }
        br.close();
    }
}

⊙ 참고 문헌

  1. 마종현, 「제로베이스 백엔드 취업 파트타임 스쿨 5기:Part 01. Java 기초-Chapter 01. Java 프로그래밍-13-2.입출력_2」, 제로베이스, 2024, https://zero-base.co.kr/
  2. 박응용, 「점프 투 자바:06장 자바의 입출력:06-02 파입 입출력」, 위키독스, 2024.07.11, https://wikidocs.net/227