본문 바로가기
개발자의 공부방/자바

BufferdReader 란?? feat. 스트림 [Stream] 이란?

by 쌈빡한 쥬니준 2019. 3. 11.
BufferdReader 란??


1
2
InputStreamReader ips = new InputStreamReader(System.in); // 이렇게 작성해도 되고 아래처럼 작성해도 된다.
// 아래와 같은 의미와 기능.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
cs



System.in

: System.in은 키보드와 같은 사용자로부터 입력을 받는 표준입력스트림 객체를 나타냅니다. 그래서, System.in의 리턴값은 InputStream입니다.

그리고, InputStream은 입력스트림으로 부터,데이터를 byte단위로 읽어오는 byte stream입니다. 


InputStreamReader

인자로, InputStream을 취해서,Reader 스트림형태로 변환합니다. 변환시, 문자열인코딩을 줄수도있습니다. 그럼, Reader스트림이란, InputStream과는 달리, 입력스트림에서, 데이터를 character단위로,처리합니다.


BufferedReader

인자로 취한 Reader 스트림에 버퍼링기능을 추가한 입력스트림 클래스 입니다.

버퍼를 둠으로써, 파일,네트워크와 같은 물리적인 장치에서 데이터를 사용자가 요청할때마다 매번 읽어오는것보단, 일정량사이즈로 한번에 읽어온후, 버퍼에 보관합니다. 그리고, 사용자가 요구시,버퍼에서 읽어오게됩니다. 결국, 속도를 향상시키고, 시간의 부하를 줄일수 있게 됩니다.

그리고, 사용자가 사용하기 편리한, readLine()과 같이 한줄씩읽어오는 메소드를 제공합니다.


정리

결국, BufferedReader을 사용하기위해서, 계속해서, 스트림을 wrap 한것입니다. 왜냐구요? BufferedReader가 사용자가 사용하기 편하고 많은기능을 제공하니까요. 복잡한 기능의 구현은 이미 Java API가 모두 해놓았구. 그리고 우리는 이것을 사용하는것이랍니다. 자바는 API에서 API로 끝나는 언어라고 말해도, 많이 틀리지는 않습니다.

 

덧붙여서, stream이 몬지 궁금하실거 같은데요. 스트림은 자바에서, 데이터 입출력시, 전송되는 데이터의 흐름을 말합니다. 간단히 설명하면, 자바에서 데이터 입출력시, 시스템을 사용한 직접적인 작업은 JVM과 JVM에의해 제공되는 라이브러리들에 의해서 처리되고, 사용자는 단지 스트림통해서, 데이터를 송신하거나 수신하기만 하면됩니다. 그래서, (데이터를 받는) 입력시, InputStream이란것을 이용한것입니다. InputStream 안쪽 작업은 자바가 구현해주는 거죠.








1) InputStream과 OutputStream


Stream이란?


컴퓨터 상의 모든 프로그램, 입출력 기기(마우스, 키보드, 모니터, 프린터 등)는 서로 다른 플랫폼 위에 만들어져 있고, 다른 언어를 사용하고 있기도 합니다. 


그렇다면, 이 프로그램들과 기계들 사이에서는 어떻게 서로 통신을 하게 될까요? 


프로그램의 함수, 구성, 언어와 상관없이 모든 프로그램은 스트림(Stream)이라는 것을 통해서 서로 정보를 주고 받게 됩니다.


스트림은 자바에서만 지원하는 기능이 이니라. OS차원에서 지원하는 기능입니다.


예를 들어서 System.out.println(“아하하하…”); 라는 명령으로 우리는 화면에 글씨를 띄울 수 있습니다. 여기에서 println이라는 메소드가 어떤 특정한 곳으로 글자를 스트림으로 쭉 뿌려주게 되죠. 그러면서 글씨가 화면에 표시되게 되는 겁니다.

 

여기에서 전달되는 데이터는 가장 하위 레벨에서 


‘01101011 01001010 10101010 11101101 …’ 


이런 식으로 바이트(바이너리)로 변환되어 입출력이 됩니다.



키보드 → 운영체제 → 프로그램



위의 그림(?)에서 → 이 부분이 바로 스트림이죠! 


키보드에서 버튼을 누르면 운영체제가 이를 캐치하고 스트림을 워드 프로그램으로 보내주어 제가 이 글을 쓸 수가 있는 것입니다. 스트림에는 크게 바이트 스트림, 문자 스트림, 데이터그램 스트림 이 있지만, 여기에선 우선 바이트와 문자 스트림을 다뤄보기로 하겠습니다. 

 

사실, 문자와 바이트 스트림의 차이는 12라는 정수가 12 그대로 받을 것인지(문자 스트림) 아니면, 0C(12)인 숫자로 받아들여질 것인지(바이트 스트림)를 제외하고는 거의 비슷합니다.

 


2) Reader(InputStreamReader)와 Writer(OutputStreamWriter)


소켓에서 문자열을 읽어 들일 때 이런 식으로 입력을 받습니다.


BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));


근데, InputStream 객체 하나로만 입출력 하지 왜 이렇게 많은 객체를 엮어서 입출력을 하는 것일까요? 알아봅시다. InputStream은 바이트(바이너리)의 흐름을 받아들이거나 내보내는 객체입니다. 분명 문자열과 Byte[]는 다른 형식의 데이터입니다.

 

‘01011010 10100111 …’ 이렇게 생긴 바이트 코드를 가지고 바로 문자로 변환시키려면 인코딩도 생각해야 되겠고, 이걸 일일이 끊어다가 문자로 바꿔서 저장하는 것도 구현을 해야 하겠고… 구현 코드가 상당히 복잡해지겠죠? 그래서 우리가 사용하는 Reader라는 객체가 있습니다. 이 객체는 이러한 바이너리 스트림을 문자로 바꿔서 읽어주는 역할을 하게 되는 거죠. 근데, 이 Reader와 Writer 객체는 한 문자 단위로 입출력을 하게 됩니다.

 

그러므로 10개의 문자로 이루어진 문자열을 입출력 하려면 write나 read를 10번 호출해야하겠죠? 이를 위해 다음에 설명드릴 Buffer를 사용하게 됩니다.


제가 이 부분의 제목을 Reader(InputStreamReader)… 라고 했는데 왜 이렇게 했나면, 우리가 흔히 쓰는 InputStreamReader가 Reader를 상속한 하위객체이기 때문입니다.

 

하위 객체들은 아래와 같이 많습니다.


Reader 클래스의 하위 클래스


InputStreamReader – 문자 스트림을 읽기 위한 클래스


BufferedReader – 다른 Reader들을 버퍼링 하기 위한 클래스


FilterReader – 필터링된 스트림으로부터 읽기 위한 클래스


PipedReader – 파이프Writer로부터 읽기 위한 클래스


ChatArrayReader – 문자 배열로부터 읽기 위한 클래스


StringReader – 문자열로부터 읽기 위한 클래스


 


3) BufferedReader와 BufferedWriter


위에서 언급한 바와 같이 BufferedReader도 또한 Reader객체의 하위 클래스입니다.

 

하지만, 단독으로 바로 InputStream을 받아서 쓰지는 않습니다. 다른 하위 객체들 (예를 들어 InputStreamReader)을 인수로 받아들여 그 Reader를 Buffering할 수 있게 도와주는 역할을 하는 것이지요.


BufferedReader와 BufferedWriter는 버퍼에 있는 입출력(IO) 클래스입니다.

 

그렇다면, 여기서 말하는 버퍼(Buffer)란 무언일까요? 버퍼는 바로 메모리를 뜻합니다.

 

메모리가 있기 때문에 읽어 들여야 할 대상과 써야 할 대상의 속도 차이 때문에 일어나는 병목현상을 줄일 수 있게 됩니다. BuffererReader의 경우에는 한 줄씩 읽어 들이는 ReadLine이라는 메소드가 있어서 한 줄을 통째로 읽어 String으로 저장을 할 수 있으므로, 구현이 한 층 더 편해집니다. Buffered를 사용하지 않았다면, 한 문자씩 읽어 들여서 조합을 해야 했겠지요. 그런데 주의할 점이 한가지 있습니다. BufferedWriter의 경우, 프로그램을 끄기 전에 반드시 버퍼를 종료시켜야 합니다. flush()나 close()를 사용하면버퍼를 닫을 수 있는데, 만약에 프로그램을 그냥 꺼버리게 되면, 이 버퍼는 길을 읽고 다시는 사용할 수 없는 자원이 되겠지요. 특히 네트워크 프로그래밍의 경우에는 반드시 flush 메소드를 호출해주어야 합니다.


BufferedReader의 생성자


BufferedReader(Reader in) : Reader in을 인자로 전달받아 BufferedReader 객체를 생성합니다.


BufferedReader(Reader in, int sz) : Reader in을 인자로 전달받아 BufferedReader 객체를 생성합니다.

여기서 BufferedReader가 내부적으로 사용하는 버퍼의 크기를 sz로 설정합니다.



원 글 출처 - 안드로이드사이드






출처 : https://m.blog.naver.com/PostView.nhn?blogId=akira54055&logNo=60040527118&proxyReferer=https%3A%2F%2Fwww.google.com%2F


출처: https://dodocap.tistory.com/entry/JAVA의-입출력-기본개념-Stream-ReaderWriter-Buffered [DoDo's BLOG]

댓글0