자바/입출력 IO

바이트 기반 스트림: Byte 입출력 스트림

백_곰 2022. 4. 24. 13:23

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문에서만 이렇게 수정해 주면 된다. )