스트림(Stream)이란?
먼저, 스트림이란? 연속적인 데이터의 흐름 또는 데이터를 전송하는 소프트웨어 모듈을 의미합니다.
아래 그림처럼, 자바에서 입출력 스트림은 우리가 작성하는 응용프로그램과 입출력 장치를 연결해줍니다.
응용 프로그램이 입력 스트림과 연결하면, 입력 스트림은 입력 장치를 제어하여 입력을 받고, 응용 프로그램에게 전달합니다.
출력도 마찬가지로, 응용 프로그램이 연결된 출력 스트림에 출력하면, 출력 스트림은 출력 장치를 제어하여 출력을 완성합니다.
즉, 자바 응용 프로그램은 입출력 스트림과만 연결하고, 입출력 스트림이 입출력 장치를 제어하고 담당하는 역할을 수행합니다.
하지만, 스트림이 실제 입출력 장치를 제어하는 것은 아닙니다.
스트림은 내부적으로 운영체제의 API인 시스템 콜을 호출하고, 실제로 입출력 장치를 제어하는 역할을 운영체제가 담당합니다.
스트림의 장점과 특징
스트림은 아래와 같은 장점이 있습니다.
- 응용 프로그램을 작성할 때, 입출력 장치를 제어하는 코드를 작성하지 않아도 된다.
- 다양한 입출력 장치를 수용할 수 있다.
스트림은 아래와 같은 특징이 있습니다.
- 스트림은
단방향이다. - 스트림은
선입선출구조이다. - 자바의 스트림은
바이트 스트림과문자 스트림으로 구분된다. - 스트림은 연결될 수 있다.
스트림은 단방향입니다. 즉, 데이터의 흐름을 나타내는 스트림은 양쪽 방향으로 흐르지 않습니다.
입력 스트림은 입력 장치만을 제어하고, 출력 스트림은 출력 장치만을 제어합니다.
다음으로, 스트림은 선입선출 구조입니다. 입력 스트림에 먼저 들어온 데이터가 응용 프로그램에 먼저 전달됩니다.
출력 스트림도 마찬가지입니다.
3, 4번 특징은 뒤에서 설명드리겠습니다.
문자 스트림 VS 바이트 스트림
바이트 스트림은 바이트 단위로 데이터를 다루는 스트림입니다.
바이트 스트림은 스트림에 들어오고 나가는 정보를 단순 바이너리로 다루기 때문에, 문자이든 이미지든 상관없이 흘려 보낼 수 있습니다.
이미지도, 파일도 내부적으로는 0과 1로 이루어져 있고, 메모리는 바이트 단위로 이루어져 있기 때문입니다.
다음으로, 문자 스트림은 2바이트의 유니코드 문자 단위로 입출력하는 스트림입니다.
하지만, 데이터는 메모리에 Byte 단위로 저장되기 때문에 문자도 내부적으로는 Byte 단위로 되어 있습니다.
따라서 문자를 입출력 할 때 Byte를 문자로 변환해주어야 합니다.
위 그림처럼 메모리 상의 byte를 유니코드 문자로 변환해주는 역할을 수행하는 게 문자 스트림입니다.
문자 스트림은 바이트들을 전달받고, 이 바이트들을 문자 집합에 있는 문자인지 비교한 후에 문자로 변환해줍니다.
하지만, 오디오와 이미지는 문자가 아니고, 바이너리 정보이기 때문에 문자 스트림을 이용해서 읽거나 쓸 수 없습니다.
정리하자면, 문자 스트림이든 바이트 스트림이든 둘 다 Byte 단위로 처리하는 것은 마찬가지입니다.
하지만, 각 스트림은 데이터를 가공하는 방법이 다를 뿐 자료의 입출력을 도와주는 중간 역할임은 동일합니다.
결론적으로 스트림은 메모리의 원시 데이터를 프로그래머가 사용할 수 있는 데이터로 바꾸어주는 역할을 합니다.
스트림의 연결
앞에서 스트림은 서로 연결될 수 있다고 했습니다.
위 코드는 키보드로부터 문자를 입력 받기 위해 표준 입력 스트림인 System.in과 InputStreamReader 스트림 객체를 연결해주는 코드입니다.
위 이미지는 System.in의 정의로, System.In은 표준입력스트림을 나타냅니다.
일반적으로 키보드와 연결되어 있고, Host와 환경에 따라 다른 입력 소스가 될 수 있습니다.
InputStreamReader는 문자 스트림 중 하나입니다.
InputStreamReader와 System.in이 연결되면, 위 이미지처럼 System.in은 키보드로부터 사용자의 키를 입력 받아서 바이트 스트림을 내보내고, InputStreamReader은 바이트 스트림을 받아서 문자로 변환한 다음 응용 프로그램에게 전달합니다.
버퍼
버퍼란, 데이터를 일시적으로 저장하기 위한 메모리입니다.
입출력 장치는 주 기억장치와는 다르게 매우 느리기 때문에 입출력 장치가 자주 동작할 수록 효율이 떨어지고, 입출력 실행 속도가 떨어지게 됩니다.
이러한 입출력을 좀 더 효율적으로 수행하기 위해서 버퍼를 사용합니다.
버퍼의 사용 예시를 들어보면, 파일에 데이터를 출력할 때, 버퍼에 데이터를 모아 두었다가, 운영체제의 API를 호출하여 한 번에 파일에 쓰게 하면, 입출력 장치를 구동하는 일이 줄어들기 때문에 속도와 효율이 올라갑니다.
참조
- 명품 자바 프로그래밍 (Chapter 8. 입출력 스트림과 파일 입출력)
- 바이트 스트림과 문자 스트림
'Java' 카테고리의 다른 글
Java의 다형성은 어떻게 동작하는가? (0) | 2022.08.19 |
---|---|
Java 입출력, Scanner와 BufferedReader의 비교 (0) | 2022.07.25 |
Java 8 / 11 / 17의 변화 (1) | 2022.07.04 |
JDBC란? (0) | 2020.07.11 |
JSTL(JSP Standard Tag Library)이란? (0) | 2020.07.09 |