Stream
이란 데이터를 주고받는 통로를 의미한다
Stream은 단방향으로만 작업이 가능하다.
따라서 입력과 출력을 위한 Stream이 따로 존재하고, 두 가지 작업을 하기 위해서는 입력스트림(InputStream)
과 출력스트림(outputStream)
이 하나씩 필요하다.
자바에서는 IO Stream을 바이트기반, 문자기반 두 가지를 제공하며, Stream은 FIFO
구조로 이루어져 있다.
byte
단위로 처리한다.바이트기반 스트림
과 바이트기반 스트림의 보조 스트림
으로 이루어져 있다.char
단위로 처리한다.문자기반 스트림
과 문자기반 스트림의 보조 스트림
으로 이루어져 있다.Byte Stream
의 최상위 부모는 InputStream
과 OutputStream
이고 이것을 상속한 클래스는 FileInputStream
, PipedInputStream
, ByteArraInputStream
이 있다.
InputStream의 read()
메서드는 받아온 정보의 byte를 반환한다.
하지만 입력방식이 다를 수 있기때문에 abstract 메서드이고, 구현은 자식클래스에서 하도록 하였다.
OutputStream은 write(int b)
라는 메서드를 abstract메서드로 제공한다.
매개변수인 int b
는 출력하기 전에 OutputStream에 저장되는 데이터이다
Sample Code
public class FileTest {
public static void main(String[] args) {
byte[] packet = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
ByteArrayInputStream bais = new ByteArrayInputStream(packet);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int data;
while( (data = bais.read() ) != -1) {
baos.write(data);
}
System.out.println(Arrays.toString(baos.toByteArray()));
}
}
출력결과
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
위의 예제는 byte배열 packet
의 데이터를 bais
라는 ByteArrayInputStream의 참조변수에 저장하고, 그 데이터를 읽어와 baos
라는 ByteArrayOutputStream의 참조변수에 저장한 후 출력하는 예제이다
위 예제에서 눈여겨 보아야 하는것은 int data
이다.
바이트 스트림은 입출력을 1byte단위로 수행한다.
그렇다면 byte
타입을 사용하면 되는데 왜 int
타입을 사용해서 메모리를 낭비할까?
EOF(-1)
을 처리하지 못하기 때문에 처리가 애매해진다.short
타입을 사용해서 처리가능하지만, 자바의 JVM도 기본 정수형 타입이 int
타입이다. 따라서 int
타입을 사용하는 것이 효율적이고 처리속도도 빠르다.위의 예제에서 바이트기반 입출력의 예시를 보았다
하지만 위의 예시에서는 1byte씩 처리하기 때문에 반복문 수행이 많을 수 밖에 없다.
반복문 수행이 많다는것은 프로그램의 성능을 저하시킬 수 있는 요인이기 때문에 최대한 줄여주는 것이 좋다
따라서 이번에는 한번에 1byte가 아닌 4byte씩 데이터를 처리하는 방법을 알아보려고 한다.
Sample Code
public class FileTest {
public static void main(String[] args) throws IOException {
byte[] packet = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
byte[] temp = new byte[4];
ByteArrayInputStream bais = new ByteArrayInputStream(packet);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
while((len = bais.read(temp)) != -1) {
baos.write(temp, 0, len);
}
System.out.println(Arrays.toString(baos.toByteArray()));
}
}
출력결과
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
이전예제와 다른점만 살펴보려고 한다
우선 len
이라는 변수가 하나 생겼는데, 이것은 bais
에서 읽어온 데이터의 길이를 저장하는 변수이다
두 번째로 read()
안에 매개변수가 생겼는데 이것은 bais
에서 읽어온 데이터를 temp
에 저장한다.
현재 temp
의 크기는 4byte이므로, 4byte만큼 읽어와야 다음 수행문을 실행한다.
이전 예제에서 1byte씩 데이터를 처리하던것을 4byte씩 처리하는 것으로 반복문의 수행횟수를 줄인것이다.
마지막으로 write(byte[] b, int off, int len)
메서드를 사용했다
매개변수의 이름에서 알 수 있듯이, b배열에 저장되어 있는 데이터를 부분적으로 가져와서 baos
에 저장하는 메서드이다.