바이트 기반 스트림: Byte 입출력 스트림
1. InputStream과 OutputStream
- 이제부터 본격적으로 바이트 기반 스트림의 메서드에 대한 예제를 해 볼 것이다.
- 일단 먼저, InputStream의 메서드들을 알아보자.
(1) int available()
: 스트림으로부터 읽어 올 수 있는 데이터의 크기를 반환한다.
(2) void close()
: 스트림을 닫음으로써 사용하고 있던 자원을 반환한다.
(3) void mark(int readlimit)
: 현재 위치를 표시해 놓는다.
: 후에 reset()에 의해서 표시해 놓은 위치로 다시 돌아갈 수 있다.
: 그러므로, 매개변수 readlimit은 되돌아갈 수 있는 byte의 수이다.
(4) void reset()
: 스트림에서의 위치를 마지막으로 mark()이 호출되었던 위치로 되돌린다.
(5) boolean markSupported()
: mark()와 reset()을 지원해주는지를 알려준다.
: mark()와 reset()을 호출하기 전에 호출해서 지원 여부를 확인해야 한다.
(6) abstract int read()
: 1byte를 읽어온다. (0~255 사이의 값)
: 더 이상 읽어 올 데이터가 없으면 -1을 반환한다.
: 추상 메서드라서, InputStream의 자손들은 자신의 상황에 맞게 구현해야 한다.
(7) int read(byte[] b)
: 배열 b의 크기만큼 읽어서 배열을 채우고 읽어 온 데이터의 수를 반환한다.
: 반환하는 값은 항상 배열의 크기보다 작거나 같다.
(8) int read(byte[] b, int off, int len)
: 최대 len개의 byte를 읽어서, 배열 b의 지정된 위치 off부터 저장한다.
: 실제로 읽어 올 수 있는 데이터가 len개보다 적을 수 있다.
(9) long skip(long n)
: 스티림에서 주어진 길이 n만큼을 건너뛴다.
- 그 다음, OutputStream의 메서드들을 알아보자.
(1) void close()
: 입력 소스를 닫음으로써 사용하고 있던 자원을 반환한다.
(2) void flush()
: 스트림의 버퍼에 있는 모든 내용을 출력 소스에 쓴다.
: 그러므로, 버퍼가 있는 출력 스트림의 경우에만 의미가 있다.
(3) abstract void write(int b)
: 주어진 값을 출력 소스에 쓴다.
(4) void write(byte[] b)
: 주어진 배열 b에 저장된 모든 내용을 출력 소스에 쓴다.
(5) void write(byte[] b, int off, int len)
: 주어진 배열 b에 저장된 내용 중에서 off번째부터 len개만큼만을 읽어서 출력 소스에 쓴다.
( 프로그램이 종료될 때, 사용하고 닫지 않은 스트림은 JVM이 자동적으로 닫아 주기는 하지만,
스트림을 사용해서 모든 작업을 마치고 난 후에는 close()를 호출해서 반드시 닫아주자. )
( ByteArrayInputStream 과 같이 메모리를 사용하는 스트림과 System.in, System.out과 같은
표준 입출력 스트림은 닫아 주지 않아도 된다. )
2. ByteArrayInputStream과 ByteArrayOutputStream
- 이 스트림은 주로 다른 곳에 입출력하기 전에 데이터를 임시로 바이트 배열에 담아서
변환 등의 작업을 하는 데 사용된다.
- 자주 사용되지 않으나 기본적인 내용이 있어 아래의 예제를 보고 이해하자.
2-1. ByteArrayInputStream과 ByteArrayOutputStream을 이해하기 위한 예제(1)
( ByteArray는 사용하는 자원이 메모리 밖에 없기 때문에 가비지 컬렉터에 의해 자동적으로 자원을
반환하므로 close()를 생략할 수 있다. )
2-2. ByteArrayInputStream과 ByteArrayOutputStream을 이해하기 위한 예제(2)
: 앞서 예제(1)의 입출력 작업이 보다 효율적으로 하기 위해 read(byte[] b, int off, int len)와
write(byte[] b, int off,int len)을 사용한 예제이다.
( 예제(1)과 다르게 temp 변수로 만들어 바구니처럼 활용했다. )
2-3. ByteArrayInputStream과 ByteArrayOutputStream을 이해하기 위한 예제(3)
: temp 변수(바구니)의 size를 값의 개수 10개가 아닌 4개로 지정하여 4개씩 읽어서 쓰는 예제이다.
( read()와 write()에서 IOException이 발생할 수 있기 때문에, try-catch문으로 감싸주었다. )
( available()는 blocking 없이 읽어 올 수 있는 바이트의 수를 반환한다. )
( blocking 이란, 데이터를 읽어 올 때 데이터를 기다리기 위해 멈춰있는 것을 뜻한다. )
( 마지막 출력문에서 예상과 다른 결과가 나오게 되었는데, 그 이유는 보다 나은 성능을 위해서
temp에 저장된 배열 값을 지우는 것이 아닌 인덱스 위치에 덮어 씌우기 때문이다. )
(1) temp = [4, 5, 6, 7]
(2) [8, 9] 읽음
(3) temp = [8, 9, 6, 7]
2-4. ByteArrayInputStream과 ByteArrayOutputStream을 이해하기 위한 예제(4)
: 위에서 출력된 값[8, 9, 6, 7]이 아닌 올바른 값 [8, 9]를 얻기 위해 코드를 수정한 예제이다.
( 위에서 했던 예제(3)의 try-catch문에서만 이렇게 수정해 주면 된다. )