자바 파일 입출력(File IO)
Stream은 시냇물을 의미하며 그 속뜻은 단방향을 의미합니다.
자바에서는 각 방향에 따라 두 개로 나누어 지는데 InputStream과 OutputStream입니다. 이 두 스트림은 바이트 단위의 입출력을 담당하는 클래스입니다.
InputStream에 대표적인 사용예는 System.in이 InputStream클래스타입이며, 컴퓨터라는 플랫폼에서는 키보드를 의미합니다. OutputStream의 대표적인 사용예는 System.out이며 모니터를 의미합니다.
그 다음 사용자들이 이해 할 수 있는 문자단위(charset)를 수행해 주는 클래스들이 있는데 그 클래스들 Reader, Writer가 있습니다. 하지만 이 두 클래스는 논리적인 구조로서 실제로 작동하기 위해서는 물리적인 구조를 나타내는 OutputStream, InputStream과 결합되어야 합니다. 그 두 구조를 중간에서 BridgeStream연결해서 만들어진 것이 InputStreamReader와 OutputStreamWriter입니다.
이 클래스들 중 OutputStream, InputStream을 node, sync stream이라고 부르고 OutputStreamReader과 InputStreamWriter를 processing, filter stream이라고 부릅니다.
문자단위로 사용할 때는 OutputStreamReader, InputStreamWriter 사용하기도 하지만 속도를 중요시 하는 경우는 InputStream, OutputStream을 사용 할 수도 있습니다. 그 이유는 문자단위(charset)는 2바이트 단위로 사용되기 때문에 번역시에 시간이 오래 걸리기 때문입니다. 그리고 음성파일, 동영상파일 같은 경우 byte단위로 처리되는 InputStream, OutputStream을 사용하게 됩니다.
파일을 입출력 할 때는 파일을 열고, 읽고, 닫는 세가지 과정을 거치는데 여는 것은 OutputStream의 인스턴스화를 통해서 파일을 열고, OutputStream의 close메서드를 이용해서 닫습니다.
파일입출력은 FileWriter, FileReader, FileInputStream, FileOutputStream클래스(nodeStream)를 사용합니다.
FileWriter, FileReader클래스를 이용하여 파일 입출력을 하는 코드입니다. 문자단위로 파일입출력을 처리하는 클래스들이고 파일 생성시에는 같은 파일이 있으면 무조건 덮어 쒸웁니다.
FileOutputStream과 FileInputStream클래스를 이용해서 파일 입출력을 하는 코드입니다. 이 두 클래스는 바이트단위로 처리를 합니다.
자바에서는 이러한 클래스들을 기반으로 입출력기능과 성능을 향상 시킬 수 있는 클래스들을 제공하고 있습니다.
클래스이름 |
설명 |
DataInputStream |
프리미티브타입의 데이터를 입출력하는 클래스 |
DataOutputStream | |
ObjectInputStream |
프리미티브타입과 레퍼런스타입의 데이터를 입출력하는 메소드 |
ObjectOutputStream | |
BufferedReader |
데이터를 한꺼번에 읽어서 버퍼에 저장해 두는 클래스 |
BufferedInputStream | |
BufferedWriter |
데이터를 버퍼에 저장해 두었다가 한꺼번에 출력하는 클래스 |
BufferedOutputStream | |
LineNumberReader |
텍스트 파일의 각 행에 번호를 붙여가면서 읽는 클래스 |
다음은 DataInputStream, DataOutputStream 클래스에서 각각의 프리미티브 데이터를 읽기 위한 메소드입니다.
메소드 설명 void writeByte(int v) 파라매터로 주어진 int타입의 값의 마지막 1바이트만 출력하는 메소드 void writeShort(int v) 파라매터로 주어진 int타입의 값의 마지막 2바이트만 출력하는 메소드 void writeChar(int v) 파라매터로 주어진 int타입의 값의 마지막 2바이트만 출력하는 메소드 void writeInt(int v) 파라매터로 주어진 int타입의 값을 출력하는 메소드 void writeLong(long v) 파라매터로 주어진 long타입의 값을 출력하는 메소드 void writeFloat(float v) 파라매터로 주어진 float타입의 값을 출력하는 메소드 void writeDouble(double v) 파라매터로 주어진 double타입의 값을 출력하는 메소드 void writeBoolean(Boolean v) 파라매터로 주어진 boolean타입의 값을 출력하는 메소드
이 메소드들은 프리미티브데이타를 파일에서 읽다가 더 이상 읽을 값이 없을 경우 EOFException이 발생하게 됩니다. 그렇기 때문에 사용 할 때 try/catch문으로 해당 Exception을 처리해 주어야 합니다.
결론적으로 맨마지막의 System.out.println()은 수행되지 않습니다. 그 이유는 while문에서 int타입의 데이터를 파일에서 읽다가 EOFException이 발생되면 Catch구문으로 프레임이 이동하게 되기 떄문인데요. 그렇기 때문에 결국 수행되지 않는 구문이기 때문에 해당 구문에 대해서 자바 컴파일러는 에러를 발생시킵니다.
즉, 무한루프바디안쪽에 break와 같은 탈출 구문이 명시적으로 없다면 무한루프 뒤쪽의 구문은 수행될 수 없기 때문에 자바에서는 오류를 발생시킵니다.
ObjectInputStream과 ObjectOutputStream은 객체를 이용해서 입출력을 수행하는 클래스입니다.
이러한 객체를 스트림으로 만드는 것을 직렬화라고 하는데 이러한 직렬화가 가능하기 위해서는 해당 클래스에서 시리얼라이즈인터페이스를 구현해야지 가능합니다.
여기서 readObject메소드의 반환타입은 Object이기 때문에 해당 디스객체의 메소드들을 사용하기 위해서는 다운캐스팅을 해주어야 합니다.
Buffered를 이용하여 입출력기능을 향상 시킨 코드입니다.
LineNumberReader클래스로 파일을 열어서 실행 할 경우 라인 번호가 출력됩니다.
PrintWriter클래스를 통해서도 파일일 열고 만들 수 있고, print메서드를 통해서 파일에 입력 할 수도 있습니다.
PrintStream클래스는 JDK초기부터 있던 클래스이다. 즉, PrintWriter클래스를 사용하는 것이 PrintStream보다 더 바람직합니다. 예전부터 PrintStream이 사용되었고 그 중 System에서 out변수는 여전히 PrintStream을 사용합니다.
File클래스는 파일을 다루기 위한 클래스입니다.
현재 디렉토리에 있는 파일,디렉토리 정보를 출력한다. 파일 생성시간은 밀리세컨으로 반환되므로 그래고리안캘린더를 이용해서 시간을 구합니다.
파일 생성, 디렉토리 생성, 임시파일 생성 예시 코드입니다.