버퍼(Buffer)
버퍼란 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 메모리의 영역을 말한다.
- 버퍼링 (buffering) 버퍼를 활용하는 방법 또는 버퍼를 채우는 과정을 말한다.
동시에 버퍼는 입력받은 값은 버퍼에 저장해두었다가 버퍼가 가득차거나 개행 문자가 나타나면 버퍼의 내용을 한 번에 전송하게 된다
그렇다면 버퍼를 왜 사용하는 걸까?
입출력을 수행하는데에 있어서 속도차이를 극복하기 위해 사용하는 임시 저장 공간인 버퍼를 사용한다.
예를 들어 입력 장치는 1초당 100개의 데이터를 전송할 수 있고, 출력 장치는 1초당 10개의 데이터를 전송받을 수 있을 때 버퍼가 없다면 입역 장치의 속도를 출력 장치의 속도에 맞춰 입력 장치의 효율이 크게 떨어진다.
- 입력 장치의 속도를 출력 장치의 속도에 맞출 경우 1초에 100개의 데이터를 전송할 수 있는 입력 장치가 10개만 전송하게 되는 것어 입력 장치의 효율이 크게 떨어진다.
입력 장치의 효율을 떨어트리지 않기 위해 입력장치에서 버퍼로 데이터를 빠르게 보낸 뒤, 버퍼에 저장된 데이터를 출력장치 속도에 맞춰 사용하게 된다.
입출력의 데이터 전송 시 작업 횟수를 줄여 부하를 방지하기 위해 버퍼를 사용한다.
만약 버터가 없다면 데이터를 보낼 때 입력 장치에서 데이터를 바로 출력 장치에 보내게 되면 자바에서 운영체제의 API 호출 횟수가 늘어 부하가 걸리게 된다.
버퍼를 사용한다면 입력 장치에서 들어오는 값을 보퍼에 보관하고 버퍼에 충분한 크기의 데이터가 쌓인다면 출력 장치로 데이터를 전송함으로 써 작업 횟수를 줄
여 장치의 부하를 낮춰준다.
이처럼 입출력 장치의 속도의 차이로인해 일을 쉬는 것을 방지고 입출력 장치의 동작 횟수를 줄임으로 효율을 높여 입출력 실행 속도가 떨어지지 않고 더 빠르고 안정적인 퍼포먼스를 낼 수 있게 해준다. 하지만 입력 작업에 버퍼를 쓰는 것이 반드시 좋은 것은 아니다. 빠른 반응이 요구되는 게임 등 프로램에선 버퍼를 사용하지 않는 것이 바람직하다.
버퍼 스트림
버퍼 스트림은 버퍼를 사용하여 입출력 효율을 높이는 스트림을 말한다.
바이트 버퍼 스트림
바이트 단위의 바이너리 데이터를 처리하는 스트림의 입출력 효율을 높이기 위해 버퍼 (byte[])를 사용하는 보조 스트림이다.
- 보조스트림을 닫으면 기반스트림도 닫힌다.
BufferedInputStream와 BufferedOutputStream
BufferedInputStream
버퍼크기는 입력소스로부터 한 번에 가져올 수 있는 데이터의 크기로 지정하면 좋다.
- 보통 입력소스가 파일인 경우 보통 작게는 1024부터 2048 또는 4096 정도의 크기로 하는 것이 보통이다
- 버퍼의 크기를 변경해가면서 테스트하면 최적의 버퍼 크기를 알아낼 수 있다.
read() 메서드를 호출하면, BufferedInputStream은 입력 소스로 부터 버퍼 크기만큼의 데이터를 읽어다 자신의 내부 버퍼에 저장한다.
- 예를 들어 2048의 크기로 BufferedInputStream의 인스턴스를 생성하고 read() 메서드를 호출하게 되면,
입력소스로부터 2048 byte 만큼 읽어와서 내부 배열에 저장하고, 2048 byte 중 1 byte만을 반환하게 된다. - read() 메서드로 내부 버퍼의 내용을 다 읽게 될 때 까지 입력소스에 추가적으로 접근하지 않게되고, 내부 버퍼의 내용을 다 읽으면 다시 입력소스에 접근해서 생성시 지정한 버퍼의 크기만큼 데이터를 읽어온다
BufferedOutputStream

BufferedOutputStream 또한 출력버퍼로 바로 전송하지 않고, 내부 버퍼에 데이터를 쌓아두었다가 버퍼의 내용이 가득차면 출력소스로 보낸다.
- 버퍼가 가득 차면, 그 때 버퍼의 모든 내용을 출력 소스에 출력한다.
버퍼가 가득 찼을때만 출력소스에 출력을 하기 때문에, 마지막 출력 부분이 출력소스에 쓰여지지 못하고 버퍼에 남아있는 채로 프로그램이 종료될 수 있다는 점을 주의해야 한다.
- 따라서 프로그램에서 모든 출력 작업을 마친 후 BufferedOutputStream에 close()나 flush()를 호출해서 마지막에 버퍼에 있는 모든 내용이 출력소스에 출력되도록 해야 한다.
문자 버퍼 스트림
- 라인(line)단위의 입출력이 편리하다.
BufferedReader와 BufferedWriter
BuffredReader와 BufferedWriter는 BufferedInputStream와 BufferedOutputStream 비슷한 기능을 제공한다.
BufferedReader
생성자 | 설명 |
BufferedReader(Reader in) | 주어진 Reader의 인스턴스를 입력 소스(input source)로하여 BufferedReader의 버퍼를 갖는 BufferedReader 인스턴스를 생성한다.(버퍼의 크기를 지정해 주지 않아 기본값인 8192 char 크기의 버퍼를 갖게 된다.) |
BufferedReader(Reader in, int size) | 주어진 Reader의 인스턴스를 입력 소스(input source)로하여 지정된 크기(char 단위)의 버퍼를 갖는 BufferedReader 인스턴스를 생성한다. |
readLine() | 버퍼으로부터 한 줄을 읽어 문자열을 리턴해주는 메소드 |
BuffredReader의 readLine()을 사용하면 데이터를 라인단위로 읽어올 수 있다는 장점이 있다.
- readLine()의 리턴 타입은 String으로 고정되기에 String이 아닌 다른 타입이 필요하다면 형변환이 필요하다.
생성자/메서드 | 설명 |
BufferedWriter(Writer out) | 주어진 Writer 인스턴스를 출력소스(ouput source)로 하여 BufferedWriter 의 버퍼를 갖는 BufferedWriter인스턴스를 생성한다. (버퍼의 크기를 지정해 주지 않아 기본값인 8192 char 크기의 버퍼를 갖게 된다.) |
BufferedWriter(Writer out, int sz) | 주어진 Writer 인스턴스를 출력소스(ouput source)로 하여 지정된 크기(char)의 버퍼를 갖는 BufferedWriter인스턴스를 생성한다. |
newLine() | 라인 구분자(개행문자)를 출력한다. |
flush() | 버퍼의 모든 내용을 출력소스에 출력한 다음, 버퍼를 비운다. |
close() | flush()를 호출해서 버퍼의 모든 내용을 출력소스에 출력하고, 인스턴스가 사용하던 모든 자원을 반납한다. |
BufferedWriter 또한 출력버퍼로 바로 전송하지 않고, 내부 버퍼에 데이터를 쌓아두었다가 버퍼의 내용이 가득차면 출력소스로 보낸다.
- 버퍼가 가득 차면, 그 때 버퍼의 모든 내용을 출력 소스에 출력한다.
버퍼가 가득 찼을때만 출력소스에 출력을 하기 때문에, 마지막 출력 부분이 출력소스에 쓰여지지 못하고 버퍼에 남아있는 채로 프로그램이 종료될 수 있다는 점을 주의해야 한다.
- 따라서 프로그램에서 모든 출력 작업을 마친 후 BufferedWriter 에 close()나 flush()를 호출해서 마지막에 버퍼에 있는 모든 내용이 출력소스에 출력되도록 해야 한다.
'Java' 카테고리의 다른 글
[JAVA] 람다 표현식(Lambda Expression) (0) | 2024.01.28 |
---|---|
[JAVA] 표준 입출력과 File 클래스, 직렬화(Serialization) (0) | 2024.01.18 |
[JAVA] 자바의 입출력과 스트림(I/O stream) (0) | 2024.01.18 |
[JAVA] 쓰레드의 동기화(synchronization) (0) | 2024.01.18 |
[JAVA] 쓰레드(thread) (0) | 2024.01.18 |