ByteArrayIOStream(바이트 배열기반 입출력 스트림)

신광진·2021년 3월 18일
0

Java

목록 보기
5/19
post-thumbnail

Stream


Stream이란 데이터를 주고받는 통로를 의미한다

Stream은 단방향으로만 작업이 가능하다.

따라서 입력과 출력을 위한 Stream이 따로 존재하고, 두 가지 작업을 하기 위해서는 입력스트림(InputStream)출력스트림(outputStream)이 하나씩 필요하다.


자바에서는 IO Stream을 바이트기반, 문자기반 두 가지를 제공하며, Stream은 FIFO구조로 이루어져 있다.

IO Stream


  • 바이트기반 스트림
    • 데이터 입출력은 byte단위로 처리한다.
    • 바이트기반 스트림과 바이트기반 스트림의 보조 스트림으로 이루어져 있다.
  • 문자기반 스트림
    • 데이터 입출력은 char단위로 처리한다.
    • 문자기반 스트림과 문자기반 스트림의 보조 스트림으로 이루어져 있다.

Byte Stream


Byte Stream의 최상위 부모는 InputStreamOutputStream이고 이것을 상속한 클래스는 FileInputStream, PipedInputStream, ByteArraInputStream이 있다.


InputStream의 read()메서드는 받아온 정보의 byte를 반환한다.

하지만 입력방식이 다를 수 있기때문에 abstract 메서드이고, 구현은 자식클래스에서 하도록 하였다.

OutputStream은 write(int b)라는 메서드를 abstract메서드로 제공한다.

매개변수인 int b는 출력하기 전에 OutputStream에 저장되는 데이터이다

ByteArrayStream Example


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타입을 사용해서 메모리를 낭비할까?

  • int타입으로 처리하는 이유
    • 1byte의 단위는 0~255지만, 자바에서는 unsigned타입이 없기때문에 127까지밖에 처리하지 못한다.
    • unsigned타입이 있다고 하더라도 EOF(-1)을 처리하지 못하기 때문에 처리가 애매해진다.
    • short타입을 사용해서 처리가능하지만, 자바의 JVM도 기본 정수형 타입이 int타입이다. 따라서 int타입을 사용하는 것이 효율적이고 처리속도도 빠르다.

read()


위의 예제에서 바이트기반 입출력의 예시를 보았다

하지만 위의 예시에서는 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에 저장하는 메서드이다.

profile
이거 왜안되냐

0개의 댓글