본문 바로가기

JAVA

ByteArrayInputstream, ByteArrayOutputStream 예제

바이트 기반 스트림 : ByteArrayInput(Output)Stream은 메모리에 데이터를 입출력하는 데 사용하는 스트림임

다른곳에 입출력하기 전에 데이터를 임시로 바이트배열에 담아서 변환 등의 작업을 하는 데 사용한다

 

package 입출력;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;

public class ex01 {

	public static void main(String[] args) {
		
		byte[] inSrc = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
		byte[] outSrc = null;
		
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
		
		input = new ByteArrayInputStream(inSrc);
		output = new ByteArrayOutputStream();
		
		int data = 0;
		
		while((data = input.read()) != -1) {
			// 입력스트림으로부터 1byte를 읽어서 반환하고, 읽을 수 없다면 -1을 반환한다
			output.write(data);
			// OutputStream의 write()를 씀
		}

		outSrc = output.toByteArray();
		
		System.out.println("Input Source :" + Arrays.toString(inSrc));
		System.out.println("Output Source :" + Arrays.toString(outSrc));
		
	}

}

 

* while문에 대해

1. data = input.read()

input은 byte배열인 inSrc을 담은 InputStream이다

input에서 read()를 통해 호출한 반환값을 변수 int = data에 저장한다. read()니까 inSrc에 있는 값 아니면 -1 둘 중 하나겠지

1이라면 ByteArrayOutputStream()을 참조하는 output에 data값을 쓴다. 출력소스에 쓴다는 의미

저 while문을 지나는 과정, 즉 output.write(data) 밑에 data를 출력해보면 다음과 같은 값이 나온다.

 

while((data = input.read()) != -1) {
			
			output.write(data);
			
			System.out.println(data);
            // 1 2 3 4 5 6 7 8 9 10
		}
        
        System.out.println(data);

 

data에는 1부터 10까지의 값이 차례대로 입력된다.

이 말은 상술했듯 input.read()로 스트림을 통해 읽어온 값이 inSrc배열을 순서대로 읽은 값과 같고

이렇게 읽은 값을 data에 저장한 다음

write()의 인자에 data를 넣어서 그 값을 ByteArrayOutputStream에 담는다.

while문을 빠져나와서 data값을 출력해보면 -1이 출력된다.

 

이후 byte배열인 outSrc에 output을 ByteArray로 형변환해서 넣어준다.

 

* byte배열은 사용하는 자원이 메모리밖에 없으므로 JVM의 가비지컬렉터에 의해 자동적으로 자원을 반환함으로

close()를 이용해서 스트림을 닫지 않아도 된다.

 

 

package 입출력;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;

public class ex02 {

	public static void main(String[] args) {
		
		byte[] inSrc = {0,1,2,3,4,5,6,7,8,9};
		byte[] outSrc = null;
		byte[] temp = new byte[10];
		
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
		
		input = new ByteArrayInputStream(inSrc); // InputStream을 통해 읽는다
		output = new ByteArrayOutputStream();

		input.read(temp, 0, temp.length); // 읽어온 데이터를 배열 temp에 담음

		output.write(temp, 5, 5);
		// write(byte[]b, int off, int len)
		// temp배열에서 temp[5]부터 5개의 데이터를 write한걸 OutputStream에 담음

		outSrc = output.toByteArray();
		// OutputStream의 내용을 byte[]로 반환하여 outSrc에 담는다

		System.out.println("Input source :" + Arrays.toString(inSrc));
		System.out.println("temp :" + Arrays.toString(temp));
		System.out.println("Output source :" + Arrays.toString(outSrc));
		
	}	
	

}

 

while문을 사용하지 않고

int read(byte[] b, int off, int len)과 void write(byte[] b, int off, int len)을 사용해서 입출력한다

배열을 이용한 입출력은 작업의 효율을 증가시킨다고 한다. 따라서 입출력 대상에 따라 알맞은 크기의 배열을 사용하는게 좋다고..

 

package 입출력;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;

public class ex03 {
	
	static void printArrays(byte[] temp, byte[] outSrc) {
		
		System.out.println("temp :" + Arrays.toString(temp));
		System.out.println("outSrc :" + Arrays.toString(outSrc));
		
	}
	
	public static void main(String[] args) {
		
		byte[] inSrc = {0,1,2,3,4,5,6,7,8,9};
		byte[] outSrc = null;
		byte[] temp = new byte[4];
		
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
		
		input = new ByteArrayInputStream(inSrc);
		output = new ByteArrayOutputStream();
		
		System.out.println("input source :" + Arrays.toString(inSrc));
		
		try {
			while(input.available() > 0) {
				// available()은 현재 읽을 수 있는 byte의 수를 반환한다
			
				input.read(temp); // 읽어온 데이터를 temp에 담는다
				output.write(temp); // output에 temp를 쓴다
				
				outSrc = output.toByteArray(); // 스트림 내용을 byte배열로 변환한다
				printArrays(temp, outSrc);
				
			}
			
		} catch(IOException e) {
			
			System.out.println(e);
			
		}
		
	}

}

 

try-catch문 안에 있는 available()은 블로킹없이 읽어올 수 있는 바이트의 수를 반환함

* 블로킹(blocking) : 데이터를 읽어 올 때 데이터를 기다리기 위해 멈춰있는 것. 사용자가 데이터를 입력하기 전까지 기다리고 있을 때 블로킹 상태에 있다고 함

출력하게 되면

input source :[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
temp :[0, 1, 2, 3]
outSrc :[0, 1, 2, 3]
temp :[4, 5, 6, 7]
outSrc :[0, 1, 2, 3, 4, 5, 6, 7]
temp :[8, 9, 6, 7]
outSrc :[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 7]

이런 식으로 나오는데, 이는 temp의 배열길이가 4칸이기 때문이다.

 

while문을 보면 ByteArrayInputStream(inSrc)인 input에서 temp에 읽은 데이터를 담고 그 데이터를 OutputStream에 담는다

그리고 byte배열의 null상태인 outSrc에 byte배열로 output을 넣는다.

0123, 4567, 89?? 형태로 차곡차곡 담는데, 마지막이 8967이다. 이는 이전에 길이 4개인 배열 temp에 담긴 값이 4567이라서

마지막 while문이 돌 때  8 9 를 담고 다음 값이 없어서 그렇다. read()가 8, 9 를 읽었다는 의미.

따라서 마지막 while문이 돌 때 temp값은 [4,5,6,7] - > [8,9,6,7]이다.

여기에서 write()는 담긴 내용을 지우고 새로 쓰는게 아니라 기존에 담긴 배열은 지우지 않는 것을 알 수 있다.

 

위의 코드에서 자연스러운 결과인 outSrc :[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 을 얻으려면 while문에서 

input.read(temp) - > int len = input.read(temp) (int값으로 저장함)

output.write(temp) - > output.write(temp, 0, len) {write(byte[] b, int off, int len) 을 사용한다}

을 써야한다. 내용 전체를 출력하는 것에서 read에서 읽어올 수 있는 수만큼 출력하는것임

 

'JAVA' 카테고리의 다른 글

FileInputStream, FileOutputStream 예제  (0) 2025.06.16
FileInputStream, FileOutputStream 메서드  (0) 2025.06.15
문자 기반 스트림 : Reader, Writer  (1) 2025.06.14
기본적인 File I/O에 대한 이해  (1) 2025.06.13
I/O - 보조 스트림  (0) 2025.06.13