파일 input/output은 언어에 상관없이 아주 자주 쓰이는 기본적인 기능 중 하나다. 지금부터 자바에서의 파일 input/output에 대해 살펴보도록 하자.
첫 번째로, 파일 output을 위해 자바의 라이브러리 클래스인 FileOutSteam
을 사용할 수 있다. 아래의 예시는 프로젝트 폴더에 "out.txt"라는 파일을 생성하고 "hello, world"를 출력한다. 파일이 생성될 경로는 변경할 수 있는데, 경로를 따로 지정해 주지 않았을 때 기본 경로는 프로젝트 폴더가 된다.
import java.io.FileOutputStream;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
FileOutputStream output = new FileOutputStream("out.txt");
String str = "hello, world";
byte[] bytes = str.getBytes();
output.write(bytes);
output.close();
}
}
FileOutputStream
을 사용하기 위해서는 FileOutputStream
뿐 아니라 IOException
을 import 해 줘야 한다. 일단 알아 두도록 하자.
Exception에 대한 내용은 차차 다루도록 한다.
위 코드가 실행되는 과정은 다음과 같다.
FileOuptutStream 객체를 생성하고 나면, write
메서드를 사용해서 파일에 무언가를 쓸 수 있다.
write
메서드는 인자로 byte 배열을 받는다.
String 클래스의 인스턴스 메서드인 getBytes
를 사용해서 String을 byte 배열로 변환할 수 있다.
파일에 원하는 것을 다 쓰고 나면, close
메서드를 사용해서 파일을 닫아 준다.
파일이 누군가에 의해 열릴 수 있기 전에 꼭 닫아 주어야 한다.
두 번째로, FileWriter
를 사용해서 파일에 무언가를 쓸 수 있다. FileOutputStream
은 파일에 byte를 쓰기 때문에, String을 바로 파일에 쓸 수 없다. 하지만 FileWriter
를 FileOutputStream
대신에 사용하면 String을 바로 쓸 수 있다!
import java.io.FileWriter;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("out.txt");
for(int i = 0; i < 10; i++) {
String str = "This is line number" + i + "\n";
fw.write(str);
}
fw.close();
}
}
FileOutputStream은 byte의 writing stream을 위한 것인 반면 FileWriter는 character의 writing stream을 위한 것이다.
PrintWriter
는 파일 출력을 위해 사용되는 좀 더 편리한 클래스이다. System.out
과 유사하다.
import java.io.PrintWriter;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
PrintWriter pw = new PrintWriter("src/cse3040/out.txt");
for(int i=0; i<10; i++) {
String str = "This is line number " + i + ".";
pw.println(str);
}
pw.close();
}
}
파일에 무언가를 쓰기 위해 FileWriter 객체를 생성하면 새 빈 파일이 열린다.
내용이 지워진 상태에서 새로운 내용을 쓰는 게 아니라 내용을 추가하고 싶다면 FileWriter 객체를 생성할 때 파일 open mode를 알려 주는 두 번째 인자를 함께 전달해야 한다.
import java.io.FileWriter;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("out.txt");
for(int i=0; i<10; i++) fw.write("This is line number " + i + "\n");
fw.close();
FileWriter fw2 = new FileWriter("out.txt", true);
for(int i=10; i<20; i++) fw2.write("This is line number " + i + "\n");
fw2.close();
}
}
PrintWriter 생성자의 경우는 append 매개변수를 가지지는 않지만 FileWriter를 사용해서 생성될 수 있다.
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
PrintWriter pw = new PrintWriter("out.txt");
for(int i=0; i<10; i++) pw.println("This is line number " + i);
pw.close();
PrintWriter pw2 = new PrintWriter(new FileWriter("out.txt", true));
for(int i=10; i<20; i++) pw2.println("This is line number " + i);
pw2.close();
}
}
파일에서 데이터를 읽는 기본적인 방법은 FileInputStream
을 사용하는 것이다. FileOutputStream
과 유사하다.
read
메서드를 사용한다.read
메서드는 1024(또는 차일의 끝) byte를 읽는다.read
메서드는 byte의 수를 반환한다. 만약 EOF에 도달하면 -1을 반환한다.import java.io.FileInputStream;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
byte[] b = new byte[1024];
FileInputStream input = new FileInputStream("out.txt");
input.read(b);
System.out.println(new String(b));
input.close();
}
}
파일이 byte 배열보다 크면, 배열의 크기와 같은 수의 byte만이 한 번의 read
메서드 호출마다 읽힐 것이다. 이 경우, 모든 파일을 읽기 위해 while loop를 사용할 수 있다.
import java.io.FileInputStream;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
byte[] b = new byte[100];
FileInputStream input = new FileInputStream("out.txt");
while(input.read(b) != -1) {
System.out.println(new String(b));
}
input.close();
}
}
그런데 위 방법의 경우 출력해 보면 글자가 중간중간, 그리고 마지막에 이상하게 출력된 경우가 있다. 왜 그럴까? 중간중간에 우리가 보이게 이상하게 출력된 것은 byte 배열의 크기에 맞는 만큼만 읽어서 출력했기 때문인데, 마지막에 이상하게 출력된 이유는 대개 다음과 같다.
read
에서 읽어야 할 파일이 20byte가 남았다고 가정해 보자.FileInputStream
보다 파일을 읽는 더 편리한 방법이 있다. FileReader
와 BufferedReader
를 사용하는 것이다. 이들을 사용하면 한 번에 한 줄씩 읽을 수 있다.
FileInputStream은 byte들을 읽기 위한 것인 반면, FileReader는 character들을 읽기 위한 것이다.
BufferedReader
는 파일에서 한 줄을 읽는 readLine
메서드를 제공한다.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class example {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("out.txt"));
while (true) {
String line = br.readLine();
if (line == null)
break;
System.out.println(line);
}
br.close();
}
}