Java IO
Stream
- Java에서 입출력을 수행하기 위해서는 Stream을 이용한다.
- Stream이란 Data를 운반하는데 사용되는 연결통로이다.
- Stream은 단방향통신만 가능하기 때문에 하나의 Stream으로는 입력과 출력을 동시에 처리할 수 없다.
- Stream은 연속적으로 Data를 주고 받는다.
- Queue와 같은 FIFO (First In First Output) 구조로 동작한다고 생각하면 이해하기 쉽다.
- Stream은 Byte단위로 Data를 전송하며 입출력 대상에 따라 각기 다른 Stream을 사용한다.
- File] => FileInputStream / FileOutputStream
- [Memory] => ByteArrayInputStream / ByteArrayOutputStream
- [Process] => PipedInputStream / PipedOutputStream
- InputStream이나 OutputStream을 상속받아 각각 read/write하는데 필요한 abstract method를 자신에 맞게 구현해 놓았다.
- [File] <=> [Memory] <=> [Process] <=> [User]
InputStream => https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html
- abstract int read()
- 1 Byte를 읽고 이 Byte에 해당하는 0에서 255 사이의 값을 Return한다.
- Stream이 끝나서 더 이상 읽어들일 Byte가 없는 경우에는 -1을 return한다.
- read method 뒤에 나오는 코드는 read method가 byte를 읽어들이기 전까지는 실행되지 않는다.
- 입출력 과정은 느려질 수 있으므로 별도의 Thread를 생성해서 처리하는게 좋다.
- 각각 InputStream의 Subclass는 각각 서로 다른 매체를 처리해야 하기 때문에 read method는 abstract로 선언되어 있다.
- Stream은 Byte단위로 Data를 전송하며 입출력 대상에 따라 각기 다른 Stream을 사용한다.
- abstract method인 read()를 호출한다.
- method의 선언부만 알고 있어도 호출이 가능하다.
- abstract method를 호출하는 Code 작성이 가능하다.
- abstract class를 상속받아서 abstract method를 구현
- abstract method를 구현한 class의 instance에서 해당 method 호출
- read()는 반드시 구현되어야하는 핵심적인 method이다
OutputStream => https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html
- abstract void write(int b)
- 실제로는 unsigned byte를 Write한다.
- Java의 경우 unsigned byte Data Type이 존재하지 않는다.
- Header를 하위 1byte만 사용되고 상위 3byte는 무시된다.
- Data를 write하는 일이 끝났다면 OutputStream을 비우는 것이 중요하다.
- Stream은 Network를 구성하는 Hardware에 Buffer에 저장하기도한다.
- Java Code로 Software에서 직접 저장할 수 있다.
- Buffer 방식의 Stream은 내장된 Stream에서 Data가 더 많이 오기 전까지는 Buffer에 들어있는 데이터를 전송하지 않는다.
[ Application Layer ] [ Application Layer ]
[ Socket ] InputStream(a) InputStream(b) [ Socket ]
OutputStream(b) OutputStream(a)
BufferedInputStream & BufferedOutputStream
=> https://docs.oracle.com/javase/8/docs/api/java/io/BufferedInputStream.html
=> https://docs.oracle.com/javase/8/docs/api/java/io/BufferedOutputStream.html
- - Stream의 I/O 효율을 높이기 위해 Buffer를 사용하는 Filter Stream이다.
- Buffer (byte array)를 이용해서 한 번에 여러 byte를 입출력하는 것이 빠르기 때문에 대부분의 입출력 작업에서 사용된다.
- BufferedStream을 Instance를 생성할 떼 Buffer의 Size를 지정해 주지 않으면 기본적으로 8192 byte Size의 Buffer를 갖게 된다.
- ☑ Buffer의 Size를 변경해가면서 최적의 Size를 결정할 수 있다.
- 한 Buffer가 가득 차면, Buffer의 모든 내용을 출력하고 Buffer를 비운다.
- Buffer가 가득 찼을 경우만 출력을 하기 때문에, Data가 BufferedOutputStream Buffer에 남아 있는 채로 프로그램이 종료될 수 있다.
- ☑ flush() 또는 close()를 호출해서 Buffer에 남아 있는 모든 data가 출력되도록 해야한다
DataInputStream & DataOutputStream => DataInputStream & DataOutputStream
- DataInputStream은 DataInput Interface를 DataOutputStream은 DataOutput Interface를 각각 구현하였다.
- Data를 read/write하는데 byte단위가 아닌, Primitive Type으로 read/write 가능하다.
- 각 자료형의 크기가 다르므로, 출력한 Data를 다시 읽어 올 때는 출력했을 때의 순서를 고려해야한다.
- 한 번에더 이상 읽을 Data가 없는 경우 EOFException을 발생시킨다.
- 무한반복문과 catch문을 이용해서 data를 읽는다.
- JDK1.7부터 try-with-resources를 이용해서 close()를 직접 호출하지 않아도 자동호출 되도록 할 수 있다.
Filter Stream => https://docs.oracle.com/javase/8/docs/api/java/io/FilterInputStream.html
- Filter Stream은 자체적으로 I/O를 수행할 수 없기 때문에 Stream을 필요로한다.
- Filter Stream의 모든 method는 단순히 Stream의 read/write method를 호출할 뿐이다
- FilterInputStream/FilterOutputStream은 상속을 통해 원하는 작업을 수행하도록 read/write method를 overriding 해야한다.
- Constructor의 access modifier가 protected이기 때문에 Filter InputStream의 Instance를 생성해서 사용할 수 없다.
- 상속을 통해서 원하는 작업을 수행하도록 read/write하는 method를 overriding 해야 한다
Buffer를 이용한 입출력 성능 향상 => BufferedInputStream / BufferedOutputStream
Digest 기능 제공 => DigestInputStream / DigestInputStream
Int, float 같은 primitive type로 data를 처리하는 기능 제공 => DataInputStream / DataOutputStream
암호화 및 복호화 기능 제공 => CipherInputStream / CipherOutputStream
Little Endian & Big Endian
- Network Protocol에서 사용되는 정수는 32bit로된 Big-Endian 형식이다.
* Little Endian => 0x04 0x03 0x02 0x01
0x100 0x101 0x102 0x103
* Big Endian => 0x01 0x02 0x03 0x03
0x100 0x101 0x102 0x103
Reader & Writer => https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html / https://docs.oracle.com/javase/8/docs/api/java/io/Writer.html
- 문자 Data 입출력을 위한 Reader와 Writer를 제공한다.
- C언어와 달리 Java에서는 한 문자를 의미하는 char형이 2byte이기 때문에 byte 기반의 Stream으로 처리하는데 문제가 존재한다.
- Java에서 문자기반의 Stream인 Reader와 Writer를 제공한다.
- 문자데이터를 입출력할 때는 byte기반의 Stream대신 문자기반 Stream을 사용하면 편리하다.
- read()를 abstract method로 하는 것보다 read(char cbuf[], int off, int len)을 abstract method로 하는 것이 더 바람직하다.
[File] => FileReader / FileWriter
[String] => StringReader / StringWriter
[Memory] => CharArrayReader / CharArrayWriter
[Process] => PipedReader / PipedWriter
'CS > Network' 카테고리의 다른 글
[Network] Network Layer (0) | 2024.03.30 |
---|---|
[Network] IP (0) | 2024.03.30 |
[Network] TCP (0) | 2024.03.30 |
[Network] 신뢰성 있는 데이터 전송의 원리 (0) | 2024.03.30 |
[Network] UDP (0) | 2024.03.30 |