만족

[JAVA] 파일 입출력(File Input/Output) 본문

[JAVA] 파일 입출력(File Input/Output)

JAVA/설명 Satisfaction 2017. 12. 19. 20:55

파일 입출력의 원리


자바에서는 '스트림'이라는 일종의 징검다리를 이용하여 파일과 자바 프로그램을 연결할 수 있다.


이 스트림으로 연결되어 있다면, 자바에서 파일의 내용을 읽어올 수 있고, 파일에 데이터를 내보낼 수도 있다.


자바만의 I/O모델을 기반으로, 어떤 형태의 데이터든지 같은 형태로 입출력이 가능하다.


​InputStream 클래스


입력(파일에서 읽어오기)에 사용되는 스트림 클래스이다.


데이터를 1byte단위로 읽어온다.


java.io 패키지에 속해 있다.


InputStream은 abstract클래스이기 때문에 직접 객체화가 불가능한데, InputStream을 상속하는 클래스를 사용하거나  재정의해야 한다.

ex) InputStream input=new FileInputStream("ex.txt"); //FileInputStream은 InputStream의 자식 클래스

//생성자의 매개값으로는 파일의 경로 전달


FileInputStream 클래스


abstract클래스인 InputStream클래스를 상속하여 변수/메소드를 재정의한 클래스이다.


FileInputStream 클래스의 주요 메소드


int read() //데이터를 1byte 읽어온다. 읽어올 데이터가 없을 경우 -1을 리턴

//1byte를 읽어오는데 int형을 사용하는 이유는, byte 자료형의 경우 -127~128을 표현 가능한데

//byte형을 사용시 읽어온 데이터가 -1일때, 이것이 데이터가 없는 경우인지, 읽어온 데이터가 -1인지 구별할 수 없기 때문이다.

//int형에서의 -1 표현법 -> 11111111 11111111 11111111 11111111

//byte형에서의 -1표현법 -> 11111111

//즉, 읽어온 데이터가 -1인 경우 00000000 00000000 00000000 11111111 이고

//읽어올 데이터가 없을 경우는 11111111 11111111 11111111 11111111 이다.


int read(byte b[]) //데이터를 b배열의 크기만큼 한번에 읽어들인다. 읽어들인 데이터의 크기를 리턴


void close() //스트림 소멸


OutputStream 클래스


​출력(파일로 내보내기)에 사용되는 스트림 클래스이다.


java.io 패키지에 속해 있다.


OutputStream클래스 역시 abstract클래스이기 때문에 직접 객체화가 불가능하다.

ex) OutputStream output=new FileOutputStream("ex.txt"); //FileOutputStream은 OutputStream의 자식 클래스

//생성자의 매개값으로는 파일의 경로 전달


FileOutputStream 클래스


abstract클래스인 OutputStream클래스를 상속하여 변수/메소드를 재정의한 클래스이다.


데이터를 1byte단위로 출력한다.


FIleOutputStream 클래스의 주요 메소드


void wrtie(int b) // b변수(int형이므로 4byte)에서 최하위 1바이트만 출력


void write(byte b[], int off, int len) //b배열의 off(index)부터 len만큼 한번에 출력


void close() //스트림 소멸


------------------------------------------------------------------------------------------------


데이터 입출력 필터 스트림


입출력 스트림은 1byte씩 데이터를 입/출력 하는데, 이럴 경우 long형은 8byte이므로 1byte씩 8번 읽어와서 그것을 조합해 주어야 하는데, 입출력 스트림으로만은 그것이 상당히 어렵다.


이와 같은 데이터의 조합을 편리하게 해 주는 것이 데이터 입/출력 스트림이다.


필터 스트림의 일종이므로 입/출력 스트림에 끼워서(참조값을 전달해서) 사용한다.


(입출력 스트림과 데이터 입출력 스트림의 모델링)


데이터 입력 필터 스트림


파일에서 읽어올 때, 입력 스트림과 함께 사용되는 필터스트림이다.


DataInputStream 클래스


입력 필터 스트림중 하나이다. (FIlterInputStream 클래스를 상속한다)


생성자의 매개값으로 InputStream의 참조값을 전달받는다.


DataInputStream filter=new DataInputStream(InputStream in);


DataInputStream 클래스의 주요 메소드


​byte readByte() //byte형 변수 읽어오기


int readInt() //int형 변수 읽어오기


long readLong() //long형 변수 읽어오기


String readLine() //문자열 한 줄 읽어오기 (개행포함)


void close() //스트림 소멸


데이터 출력 필터 스트림


파일로 데이터를 출력할 때, 출력 스트림과 함께 사용되는 필터스트림이다.


DataOutputStream 클래스


출력 필터 스트림중 하나이다. (FilterOutputStream 클래스를 상속한다.)


생성자의 매개값으로 OutputStream 의 참조값을 전달받는다.


DataOutputStream filter=new DataOutputStream(OutputStream out);


DataOutputStream 클래스의 주요 메소드


void writeByte(int v) // 읽어온 4byte중 3byte를 버리고 1byte 출력


void writeChar(int v) // 읽어온 4byte중 2byte를 버리고 2byte출력


void writeInt(int v) //읽어온 4byte를 출력


void writeLong(long v) //읽어온 8byte를 출력


void close() //스트림 소멸


------------------------------------------------------------------------------------------------

 

버퍼 필터 스트림


내부적으로 버퍼(buffer)를 지닌 입출력 스트림이다. 


내부적으로 버퍼(byte b[])를 지니고 있으며, 버퍼가 모두 채워지면, 한번에 입/출력하기 때문에 입/출력 속도가 매우 빠르다.


특정 메소드를 호출하지 않아도 버퍼는 자동으로 채워진다.


필터 스트림의 일종이므로 입/출력 스트림에 끼워서(참조값을 전달해서) 사용한다.

(버퍼 필터 스트림도 데이터 필터 스트림과 같은 필터 스트림의 일종이므로 사용 방법은 동일하다)


입력 버퍼 필터 스트림


입력 스트림과 함께 사용되는 버퍼 필터 스트림이다.

(FilterInputStream 클래스를 상속한다.)


BufferedInputStream 클래스


입력 버퍼 필터 스트림이다.


내부적으로 버퍼를 지니고 있으며, 생성자에 InputStream 의 참조값을 전달하거나 참조값과 버퍼의 크기를 임의로 전달할 수도 있다.


BufferedInputStream bInput=new BufferedInputStream(InputStream in);

또는

BufferedInputStream bInput=new BufferedInputStream(InputStream in, int size);


BufferedInputStream 클래스의 주요 메소드


int read() //버퍼의 크기만큼 데이터를 읽어온다.


int read(byte b[], int off, int len) //b배열에 off에서 len까지 만큼의 데이터를 읽어온다


void close() //스트림 소멸


출력 버퍼 필터 스트림


출력 스트림과 함께 사용되는 버퍼 필터 스트림이다.

(FilterOutputStream 클래스를 상속한다.)


BufferedOutputStream 클래스


​출력 버퍼 필터 스트림이다.


내부적으로 버퍼를 지니고 있으며, 생성자에 OutputStream의 참조값을 전달하거나 참조값과 버퍼의 크기를 임의로 전달할 수도 있다.


BufferedOutputStream boutput=new BufferedOutputStream(OutputStream out);

또는

BufferedOutputStream boutput=new BufferedOutputStream(OutputStream out, int size);


BufferedOutputStream클래스의 주요 메소드


void write(int b) //읽어온 4바이트 중 3바이트를 버리고 1바이트를 파일에 출력


void write(byte b[], int off, int len) //b배열의 off부터 len까지의 데이터를 파일에 출력


void flush() //버퍼 비우기

//여기에서 버퍼를 비운다 함은 단순히 데이터를 지우는 것이 아니라

//버퍼에 잔류하고 있는 데이터들을 파일에 모두 출력한다는 것을 의미한다

//그런데 flush()메소드의 빈번한 호출은 시스템에 상당한 무리를 주므로

//반드시 필요한 상황이 아니라면 사용을 자제하는 것이 좋다.


void close() //스트림의 소멸

//close()메소드가 호출되면 자동으로 flush()메소드가 호출된다.


------------------------------------------------------------------------------------------------


버퍼 필터 스트림과 데이터 필터 스트림의 동시 사용


버퍼 필터 스트림은 입출력 속도 향상에 도움을, 데이터 필터 스트림은 읽어온 데이터들을 조합하여 

다양한 자료형의 입출력을 가능하게 한다.


그렇다면 버퍼 필터 스트림과 데이터 필터 스트림의 이점을 모두 가져갈 수는 없을까?


물론 가능하다.


버퍼 필터 스트림과 데이터 필터 스트림의 생성자의 매개변수를 보면 둘다 입/출력 스트림의 참조값을 요구함을 알 수 있다.


그런데 버퍼 필터 스트림과 데이터 필터 스트림은 모두 필터 스트림을 상속하고, 필터 스트림은 입출력 스트림을 상속하므로

입출력 스트림의 참조값 대신 버퍼 필터 스트림이나 데이터 필터 스트림을 전달할 수 있는 것이다.


 

(스트림들의 계층도)


이해가 잘 되지 않는다면, 상속의 속성을 이용하여 "상위클래스 참조변수명=new 하위클래스(매개변수);" 가 가능함을 상기하자.


어떻게 사용하는가?


세가지 스트림을 한번에 조합하는 만큼 순서가 매우 중요하다.


먼저 필터 스트림은 입출력 스트림에 끼워 사용하는 스트림이므로

가장 앞쪽에는 입출력 스트림이 위치하고 그 뒤에 필터 스트림이 존재해야 한다.


정석을 제시하면 "입출력 스트림-버퍼 필터 스트림-데이터 필터 스트림"의 순서로 조합해야 하는데

왜 버퍼 필터 스트림이 데이터 필터 스트림보다 앞서야 하는 지는 밑에서 설명하기로 하고, 먼저 사용법을 소개하겠다.


입력 스트림을 기준으로 설명하면


InputStream input=new FileInputStream("test.txt"); //test.txt와 JAVA간의 입력 스트림 생성

BufferedInputStream bufInput=new BufferedInputStream(input); //버퍼 필터 스트림과 입력 스트림의 연결

DataInputStream dataInput=new DataInputStream(bufInput); //데이터 필터 스트림과 버퍼 필터 스트림의 연결


또는 간략화하여


DataInputStream inpu=new DataInputStream(new BufferedInputStream(new FileInputStream("test.txt")));


처럼 쓸 수도 있다.


왜 순서가 중요한가?


만약 "입출력 스트림-버퍼 필터 스트림-데이터 필터 스트림"이 아니라, 순서를 바꾸어

"입출력 스트림-데이터 필터 스트림-버퍼 필터 스트림"의 순서로 조합되어 있다고 하자.


데이터 필터 스트림은 바이트 단위로 데이터를 받아들여 그것을 자료형에 맞게 조합하여 입/출력 해주는 스트림이다.


long형으로 입력받는다고 하면 데이터 필터 스트림은 8byte의 데이터를 버퍼 필터 스트림에 전달할 것인데,

버퍼 필터 스트림의 버퍼는 byte형 이라서 8byte나 되는 데이터를 저장할 수 없다.

(버퍼 필터 스트림은 바이트 단위로 데이터를 입/출력한다)


byte자료형 버퍼에 8byte 데이터를 한번에 우겨넣으려고 하니 Exception이 발생되는 것이다.


따라서 순서를 잘 지키는 것이 중요하다.


 

("입출력 스트림-데이터 필터 스트림-버퍼 필터 스트림" 의 모델링)






Comments