텍스트 파일을 읽어들이기 위해서는 FileReader와 BufferedReader가 필요합니다. FileReader 클래스는 파일에 저장된 바이트를 유니코드 문자로 변환해서 읽어들이는 역할을 담당하고, BufferedReader는 FileReader로 읽어들인 내용을 버퍼링 하여 문자, 문자 배열, 문자열 라인 등을 보다 효율적으로 처리하도록 돕는 역할을 합니다.


BufferedReader는 readLine() 메소드를 통해 \n이나 \r을 만나기 전까지의 문자열을 한 줄로 인식하여 읽어들이는 메소드입니다. 이를 바탕으로 해서 더이상 읽을 내용이 없을 때까지 내용을 가져와서 콘솔에 출력을 하는 프로그램을 만들어 보기로 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
 
public class ReadFromFile {
    public static void main(String args[]) {
        BufferedReader bReader = null;
        
        try {
            
            String s;
            File file = new File("test1.txt");
            bReader = new BufferedReader(new FileReader(file));
            
            // 더이상 읽어들일게 없을 때까지 읽어들이게 합니다.
            while((s = bReader.readLine()) != null) {
                System.out.println(s);
            }
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(bReader != null) bReader.close();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}
 
cs


반응형

텍스트 파일을 생성하고 파일에 텍스트 쓰기 세번째 글입니다.


앞서서 설명한 내용과 이번에 설명할 내용의 가장 큰 차이점은, 앞에서 설명한 방식은 Writer를 활용한 쓰기를 말한 것이며 이번에는 OutputStream을 활용한다는 것입니다. FileOutputStream은 OutputStream을 상속한 클래스로서, 파일로 바이트 단위의 출력을 내보내는 클래스 입니다.


 파일에 내용을 쓸 때 FileWriter 및 BufferedWriter를 쓰는 경우와 비교를 했을 때 차이점은, 출력하고자 하는 대상을 먼저 바이트 배열로 바꿔줘야 한다는 것입니다. 왜냐면 앞서 언급된 FileOutputStream의 상위 클래스인 OutputStream은 바이트 단위의 출력을 다루기 때문입니다. 이 과정을 통해 출력 대상 데이터가 일련의 이진 데이터 (binary data)로 변환됩니다.


그리고 flush() 메소드까지 호출한 후에 close() 메소드를 통해 FileOutputStream의 인스턴스를 닫아주어야 한다는 점도 다른점입니다.


예제 코드는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class WriteToFile {
    public static void main(String args[]) {
        
        String message = "This is a sample message.\n";
        
        File file = new File("test1.txt");
        FileOutputStream fos = null;
        
        try {
            fos = new FileOutputStream(file);
            
            // FileOutputStream 클래스가 파일에 바이트를 내보내는 역할을 하는 클래스이므로
            // 내보낼 내용을 바이트로 변환을 하는 작업이 필요합니다.
            byte[] content = message.getBytes();
            
            fos.write(content);
            fos.flush();
            fos.close();
            
            System.out.println("DONE");
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fos != null) fos.close();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}
 
cs


반응형

바로 직전에 FileWriter를 활용하여 텍스트 파일에 글을 남기는 방법을 알아보았습니다. 이번 글에서는 FileWriter에다가 BufferedWriter까지 활용하여 글을 남기는 방법을 알아보도록 하겠습니다.


근데, 왜 FileWriter만으로도 할 수 있는 작업을 BufferedWriter까지 활용해야 하냐구요? 바로 성능의 문제입니다.


작은 데이터를 쓰는 경우에야 FileWriter만으로도 큰 문제가 없지만, 100K 내외 이상의 데이터를 써야 하는 경우에는 성능상으로 봤을 때 BufferedWriter를 함께 사용하는 것이 더 효율적이라고 합니다. 그렇다면 여기서 등장하는 버퍼 (buffer)라는 개념은 무슨 의미일까요?


버퍼라는 단어 자체는 '완충'이라는 의미를 갖고 있습니다. 그리고 컴퓨터 과학에서 말하는 버퍼는 데이터가 한곳에서 다른 곳으로 이동하는 동안 일시적으로 그 데이터를 저장하는 메모리 공간을 의미합니다. 버퍼에 일정 이상의 데이터가 담기면 그 데이터는 다른 곳으로 전송이 되고, 새로운 데이터가 담기게 되는 과정을 반복합니다. 만약 버퍼가 없는 상태로 입출력을 주고 받는 경우라면, 입출력이 될때마다 매번 데이터를 처리하는 과정을 거쳐야 하므로 CPU 사용 횟수와 메모리 접근 횟수가 많아집니다. 버퍼를 사용함으로써 CPU 사용 횟수와 메모리 접근 횟수를 줄일 수 있으며, 따라서 입출력의 속도를 개선할 수 있는 겁니다. 


코드를 보이기에 앞서 우선 글로 사용법을 설명하자면, 이 역시 어려울것 하나 없습니다. BufferedWriter 인스턴스를 하나 더 생성하고, 그 인스턴스의 인자로 FileWriter 인스턴스를 집어넣으면 끝입니다. 그리고 write()와 flush() 메소드가 BufferedWriter 인스턴스를 통해 쓰여지게 하면 됩니다.


다음은 예제 코드입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
 
public class WriteToFile {
    public static void main(String args[]) {
        
        String message = "This is a sample message.\n";
        
        File file = new File("test1.txt");
        FileWriter writer = null;
        BufferedWriter bWriter = null;
        
        try {
            writer = new FileWriter(file, true);
            bWriter = new BufferedWriter(writer);
            
            bWriter.write(message);
            bWriter.flush();
            
            System.out.println("DONE");
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(bWriter != null) bWriter.close();
                if(writer != null) writer.close();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}
 
cs


반응형

.txt 파일을 생성하고 여기에 텍스트를 쓰는 방법으로는 일단 다음과 같은 두가지 방법을 알고 있습니다.

1. FileWriter를 이용하여 쓰기

2. BufferedWriter 및 FileWriter를 이용하여 쓰기

3. FileOutputStream 클래스를 이용하여 쓰기


이 중에서 이 글에서는 FileWriter를 이용하여 글을 쓰는 방법을 알아보겠습니다. 


FileWriter 클래스

파일에 문자를 쓰기 위해 활용되는 클래스로 OutputStreamWriter를 상속하고 있습니다. 

FileWriter 클래스만을 활용하여 파일에 내용을 쓰는 경우, FileWriter 객체를 생성하고 그 인자로 File 인스턴스를 담은 뒤에 여기에 내용을 쓰고 flush()를 호출해 주면 됩니다.


다음과 같이 쓸 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
 
public class WriteToFile {
    public static void main(String args[]) {
        
        String message = "This is a sample message.\n";
        
        File file = new File("test1.txt");
        FileWriter writer = null;
        
        try {
            // 기존 파일의 내용에 이어서 쓰려면 true를, 기존 내용을 없애고 새로 쓰려면 false를 지정한다.
            writer = new FileWriter(file, true);
            writer.write(message);
            writer.flush();
            
            System.out.println("DONE");
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(writer != null) writer.close();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}
 
cs


그런데, 위의 코드에서처럼 flush() 메소드를 호출하지 않고 실행을 해봐도 여전히 파일에 텍스트 메세지가 쓰여지는 것을 알 수 있었습니다.

그렇다면 이 flush() 메소드는 도대체 뭔가요?


위의 질문에 대한 답을 하기 전에 다른 질문 하나만 던져볼까 합니다. 파일에 내용을 쓰는 것은 입력이라고 할까요, 아니면 출력이라고 할까요?


이 질문에 답하기 위해 확실히 할 점은, 자바 IO에서 말하는 Reader, Writer, InputStream, 그리고 OutputStream의 주체는 바로 컴퓨터 자신이라는 겁니다. 즉,


컴퓨터가 파일을 읽어 들이는 경우에는 입력이 되는 것이고 (read IN, '읽어들임'이라고 이해하면 좀 더 쉬울까요?),

그 반대로 컴퓨터가 파일에 글을 쓰는 경우는 출력이라고 한다는 겁니다 (write OUT, '써서 내보내다'라고 이해하면 나을것 같습니다).


따라서 위의 샘플 코드는 파일에다 글을 쓰는, 즉 출력에 해당하는 작업인 것입니다.


다시 첫번째 질문으로 돌아가 보겠습니다. 컴퓨터가 파일에 내용을 쓰는 경우, 버퍼 (Buffer)라는 개념이 등장합니다. 버퍼는 일종의 완충지대인데요,

컴퓨터 입출력 속도를 높이기 위해 도입된 개념입니다.


모든 출력은 도착 지점으로 바로 나가지 않고 이 버퍼에 먼저 쌓이는데요, 여기서 flush()를 해주어야만 비로소 쌓인 버퍼를 목적지로 내보내게 되는 겁니다.


즉 flush()를 해주지 않으면 목적지에 내용이 도착하지 않을 수 있다는 것입니다. 그렇기 때문에 write() 메소드 호출 후에 꼭 flush()를 하는 것을 잊지 말아야 합니다.


이렇게 텍스트 파일을 생성하고 파일에 텍스트를 쓰는 기능은 나중에 소프트웨어 개발에서 로그 등을 저장할 때 유용하게 쓰일 수 있을거라고 생각됩니다.


반응형

+ Recent posts