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
BufferedOutputStream (Java Platform SE 8 )
Writes len bytes from the specified byte array starting at offset off to this buffered output stream. Ordinarily this method stores bytes from the given array into this stream's buffer, flushing the buffer to the underlying output stream as needed. If the
docs.oracle.com
OutputStream (Java Platform SE 8 )
Flushes this output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such b
docs.oracle.com
'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 |