스트림
자바에서도 여러 입출력을 지원하지만 이번에 우리의 관심사는 바로 자바에서 제공하는 파일 입출력입니다.
그 전 우리는 스트림에 대한 이야기를 잠깐 간략하게 하고 넘어가겠습니다. 우선 파일에서 입력과 출력이라는 동작을 하려면 파일로 데이터를 전달하거나 파일로부터 전달 받는 길을 열어주어야합니다.
그러한 길을 스트림이라고 하지요.
파일로부터 입력을 받는 스트림을 입력스트림, 출력을 보내는 스트림을 출력스트림이라고 합니다.
그리고 바이너리 형태로 데이터를 입출력하는 스트림을 이진스트림, 문자형태로 입출력하는 스트림을 텍스트스트림이라고 합니다.
스트림을 알았으니 파일입출력을 알아보도록 합시다.
FileReader와 FileWriter
import java.io.*; public class Main { public static void main(String[] args) throws IOException{ File file=new File("test.txt"); if(!file.exists()) file.createNewFile(); FileWriter fw=new FileWriter(file); char []buf= {'m','e','s','s','a','g','e','\r','\n'}; for(int i=0;i<buf.length;i++) fw.write(buf[i]); fw.close(); FileReader fr=new FileReader(file); int EOF=-1; int c; while((c=fr.read())!=EOF) { System.out.print((char)c); } fr.close(); } }
이 코드는 test.txt파일에 "message"라는 문자열을 기록하고 읽어오는 프로그램이에요. 한줄 한줄씩 보도록 하지요.
우선 File 입출력시에는 IOException이 발생할 수 있고 처리가 귀찮으니 저 멀리 보내버리도록 합시다. 가버렷!
일단 file을 열어줘야겠지요? 절대 경로로 지정하지 않는다면 현재 프로젝트 디렉토리에 파일을 엽니다.
하지만 그 파일이 없다면 새로 생성합니다.
이것을 다음의 라인이 나타냅니다.
File file=new File("test.txt"); if(!file.exists()) file.createNewFile();
그 후 파일에 "message"라는 문자열을 기록합니다. 그때 사용하는 클래스가 바로 FileWriter라는 클래스이지요.
FileWriter의 메소드 write를 통해서 char 배열의 문자열을 하나씩 기록한 후 스트림을 닫습니다.
닫아주어야 파일에 문자열이 입력이 됩니다! 파일을 닫지 않고 파일에 입력하려면 그렇지 않으면 flush함수를 사용하세요.
FileWriter fw=new FileWriter(file); char []buf= {'m','e','s','s','a','g','e','\r','\n'}; for(int i=0;i<buf.length;i++) fw.write(buf[i]); fw.close();
이후 한문자씩 읽어오는데 그 역할을 수행하는 클래스가 바로 FileReader입니다. 파일의 끝은 int형의 -1입니다. 그래서 -1을 만날때까지 한문자 한문자 출력합니다.
int형태로 읽어왔으니 char로 바꿔줘야겠지요?
FileReader fr=new FileReader(file); int EOF=-1; int c; while((c=fr.read())!=EOF) { System.out.print((char)c); } fr.close();
이제 수행을 해보도록 할게요. 어떤 변화가 있는지..
test.txt라는 파일이 생겼네요!
이것을 까보면!
그안에 우리가 집어넣은 문자열이 존재하는 군요.
eclipse상의 결과 역시 "message"라는 문자열을 출력하는 군요.
파일에 기록한 문자열을 자바프로그램이 읽어온 것이랍니다.
한글자 한글자 읽어오는 것이 여간 불편한 것이 아니죠?
문자열을 사용해서 쓰는 것이 훨씬 더 편할텐데요.
그리고 읽어올때도 배열을 써서 읽어오는 것이 훨씬 편하구요.
그런 방법이 아래에 나와있습니다.
import java.io.*; public class Main { public static void main(String[] args) throws IOException{ File file=new File("test.txt"); if(!file.exists()) file.createNewFile(); FileWriter fw=new FileWriter(file); fw.write("Hello, world!!\r\n"); fw.close(); FileReader fr=new FileReader(file); while(true) { char []buf=new char[4]; int ret=fr.read(buf); if(ret==-1) break; System.out.print(String.valueOf(buf)); } fr.close(); } }
FileWriter는 String을 받는 write메소드가 있어서 문자열로 그대로 파일에 기록할 수 있습니다.
중요한건 FileReader인데요. 우선 buf라는 char형 4개에 문자열을 계속 입력받는 거지요. 만약 파일에서 더 읽어올 것이 없다면 -1을 리턴하게 되니까 그 반환형이 -1이면 while루프를 탈출하면 됩니다.
이제 실행 후 파일을 확인해보고 이클립스에서도 확인해 봅시다.
파일에 제대로 적혀있고 이클립스 출력도 이 문자열이 나오는 것을 확인할 수 있죠?
Line 단위 입출력
아직도 불편하긴 합니다. /r/n을 통해서 개행하는 것도 별로구요. 보통 문자 입출력시에는 라인 단위로 입출력을 하기 때문에 라인별로 입력을 할 수 있었으면 좋겠습니다.
그래서 나온것이 버퍼단위의 입출력을 담당하고 있는 BufferedReader, BufferedWriter입니다.
import java.io.*; public class Main { public static void main(String[] args) throws IOException{ File file=new File("test.txt"); if(!file.exists()) file.createNewFile(); BufferedWriter bw=new BufferedWriter(new FileWriter(file)); bw.write("Hello, world!"); bw.newLine(); bw.write("Hello, world!!"); bw.newLine(); bw.write("Hello, world!!!"); bw.newLine(); bw.close(); BufferedReader br=new BufferedReader(new FileReader(file)); String line=null; while((line=br.readLine())!=null) System.out.println(line); br.close(); } }
BufferedWriter와 BufferedReader는 버퍼의 사이즈를 지정할 수도 있습니다. 그렇지 않으면 Default 사이즈로 버퍼에 담습니다.
BufferedWriter의 newLine메소드는 개행을 말합니다. 쉽죠? 별거 없어요.
여기서는 Hello, world!를 3라인에 걸쳐 출력합니다. (느낌표 갯수만 다르고요)
이제 BufferedReader를 통해서 읽어옵니다.
readLine은 String 형태의 문자열을 반환하는데, 만약 더이상 출력할 문자열이 없으면 null을 반환하죠.
그래서 null을 만나게 되면 while루프를 탈출합니다.
이제 실행후 파일과 이클립스화면을 보면 둘의 결과는 같다는 것을 알 수 있습니다.
test.txt
이클립스 실행결과
Hello, world!
Hello, world!!
Hello, world!!!
어떻습니까?
BufferedReader와 BufferedWriter 정말 편리하죠?
이 두 클래스는 조금 빈번하게 쓰입니다. 기억해두세요.
아직 파일입출력에 대해서는 더 할 이야기가 나왔습니다. 나중에 더 이야기 해보도록 하지요.
'언어 > JAVA' 카테고리의 다른 글
[자바/JAVA] 문자열 다루기 2 String getBytes 인코딩, 디코딩 (0) | 2019.05.05 |
---|---|
[자바/JAVA] 문자열 다루기1 String 클래스 메소드 (0) | 2019.05.05 |
[자바] 추상클래스와 인터페이스 개념과 사용방법 (0) | 2018.12.23 |
[JAVA] 자바 다형성(Polymorphism) 개념부터 응용 쉬운 설명 (13) | 2018.12.23 |
[JAVA] 캡슐화, 접근 제어자(private, default, protected, public) (0) | 2018.10.09 |