2) 파일 입출력

파일 생성하기

 

다음을 작성해서 실행해 보면 c:/ 디렉토리에 새로운 파일(out.txt)이 하나 생성되는 것을 확인할 수 있다.

 

Test.java


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

public class Test {
    public static void main(String[] args) throws IOException {
        FileOutputStream output = new FileOutputStream("c:/out.txt");
        output.close();
    }
}

 

파일을 생성하기 위해서 우리는 FileOutputStream 클래스를 사용했다.

 

위의 예에서보면 output.close()라는 문장이 있는데 이것은 열린 파일 객체를 닫아주는 것이다. 사실 이 문장은 생략해도 된다. 왜냐하면 자바 프로그램이 종료할 때 열린 파일 객체를 자동으로 닫아주기 때문이다. 하지만 직접 열린 파일을 닫아주는 것이 좋다. 열었던 파일을 닫지 않고 다시 사용하려고 할 경우에는 에러가 날 수 있기 때문이다.

 

파일에 내용쓰기

 

이번에는 프로그램의 출력값을 파일에 적어 보도록 하자.

 


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

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

 

FileOutputStream에 값을 쓸 때는 byte배열로 써야 하므로 위와같이 String을 byte배열로 바꾸어 주는 getBytes() 메써드를 이용해야만 했다. \r\n은 줄바꿈 문자이다. (※ 유닉스인 경우는 \n 만 있으면 된다. 윈도우즈의 경우 \r\n 처럼 \r 문자를 추가해야 노트패드 같은 에디터에서 줄바꿈이 제대로 표시되어 보인다.)

 

문자열을 파일에 쓸 때에는 FileOutputStream이 좀 불편하다. String을 byte배열로 변환해야 하기 때문이다.

 

좀 더 편리한 방법은 없을까?

 

다음의 예제를 보도록 하자.


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

public class Test {
    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 를 이용하면 byte 배열 대신 문자열을 직접 파일에 쓸 수가 있다.

 

하지만 \r\n을 문자열 뒤에 덧 붙여야 하는 귀찮음은 여전히 남아있다. PrintWriter를 이용하면 \r\n을 덧붙이는 대신 println이라는 메써드를 사용할 수 있게 된다.

 

다음은 PrintWriter를 이용하여 파일을 작성하는 예제이다.

 


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

public class Test {
    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();
    }
}

 

위의 프로그램을 다음의 프로그램과 비교해 보자.

 


for(int i=1; i<11; i++) {
    String data = i+" 번째 줄입니다.";
    System.out.println(data);
}

 

두 프로그램의 서로 다른 점은 data를 출력시키는 방법이다. 두 번째 방법은 우리가 지금껏 계속 사용해 왔던 모니터 화면에 출력하는 방법이고 첫 번째 방법은 모니터 화면대신에 파일에 결과값을 적는 방법이다. 차이점이 금방 눈에 들어 올 것이다. 두번째 방법의System.out대신에 PrintWriter를 이용했을 뿐이다.

 

첫 번째 예제를 작성해서 실행시키면 c:/out.txt 파일이 생성된다. 그리고 파일이 어떤 내용을 담고 있는 지 확인 해 보자. 아마 다음과 같을 것이다.

 

out.txt의 내용


1 번째 줄입니다.
2 번째 줄입니다.
3 번째 줄입니다.
4 번째 줄입니다.
5 번째 줄입니다.
6 번째 줄입니다.
7 번째 줄입니다.
8 번째 줄입니다.
9 번째 줄입니다.
10 번째 줄입니다.

 

즉 두 번째 방법을 사용했을 때 모니터 화면에 출력될 내용이 파일에 고스란히 들어가 있는 것을 알 수 있다.

 

파일에 내용 추가하기

 

프로그램을 만들다 보면 파일에 내용을 쓰고 파일객체를 닫은 후에 또 새로운 내용을 추가하고 싶을 때가 생긴다. 이런 경우에는 파일을 추가모드로 열어야 한다.

 

다음의 예제를 보자.


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

public class Test {
    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);
        for(int i=11; i<21; i++) {
            String data = i+" 번째 줄입니다.\r\n";
            fw2.write(data);
        }
        fw2.close();
    }
}

 

fw2라는 객체는 FileWriter("c:/out.txt", true) 와 같이 두번째 입력값이 추가로 입력되어 생성되었다. 두번째 boolean 입력 파라미터는 파일을 추가모드(append)로 열것인지에 대한 구분값이다.

 

new FileWriter(파일명, 추가모드구분)

 

위 코드를 실행하면 out.txt파일에 fw2로 추가한 내용이 파일에 적혀 있음을 확인할 수 있을 것이다.

 

만약 PrintWriter를 이용하고 싶은 경우에는 다음과 같이 변경하면 된다.

 


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

public class Test {
    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();


        PrintWriter pw2 = new PrintWriter(new FileWriter("c:/out.txt", true));
        for(int i=11; i<21; i++) {
            String data = i+" 번째 줄입니다.";
            pw2.println(data);
        }
        pw2.close();
    }
}

 

PrintWriter의 생성자로 추가모드로 파일을 연 FileWriter를 객체를 전달했다.

 

파일 읽기

 

이제 파일을 읽어 보도록 하자.


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

public class Test {
    public static void main(String[] args) throws IOException {
        byte[] b = new byte[1024];
        FileInputStream input = new FileInputStream("c:/out.txt");
        input.read(b);
        System.out.println(new String(b));
        input.close();
    }
}

 

위와 같이 FileInputStream을 이용하면 파일을 읽을 수 있다. 다만 byte 배열을 이용하여 파일을 읽어야 하기 때문에 얼만큼 읽어야 하는지 size를 모를 경우 좀 불편한 방법이다.

 

만약 라인단위로 파일을 읽는다면 다음의 방법이 훨씬 좋을 것이다.

 


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

public class Test {
    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;
            System.out.println(line);
        }
        br.close();
    }
}

 

FileReader로 파일을 character 단위로 읽도록 변경한 후에 BufferedReader로 감싸면 readLine 메소드를 이용하여 라인단위로 파일을 읽을 수 있다.

 

readLine 메소드는 더이상 읽을 라인이 없을 경우 null을 리턴한다.

 

위 예는 파일을 라인단위로 읽어서 출력하고 더 이상 읽을 라인이 없는 경우 while문을 빠져나간다.