바이트 기반 스트림 : 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 |