자바에서 데이터는 스트림을 통해 입출력된다. 스트림은 단일 방향으로 연속적으로 흘러가는 것을 말하는데, 물이 높은 곳에서 낮은 곳으로 흐르듯이 데이터는 출발지에서 도착지로 흘러간다.
프로그램이 출발지냐 또느 도착지냐에 따라서 사용하는 스트림의 종류가 결정된다. 프로그램이 도착지이면 흘러온 데이터를 입력받아야 하므로 입력 스트림을 사용한다. 반대로 프로그램이 출발지면 데이터를 출력해야 하므로 출력 스트림을 사용한다.
입출력 스트림의 종류
java.io 패키지에는 여러 가지 종류의 스트림 클래스를 제공하고 있다. 이들 스트림 클래스는 아래와 같이 크게 두 종류로 구분된다.
- 바이트 기반 스트림 : 그림, 멀티미디어 등의 바이너리 데이터를 읽고 출력할 때 사용
- 문자 기반 스트림 : 문자 데이터를 읽고 출력할 때 사용
스트림 클래스가 바이트 기반인지, 문자 기반인지를 구별하려면 최상위 클래스를 보면 된다. 아래 포는 바이트 기반 스트림과 문자 기반 스트림의 최상위 클래스와 하위 클래스의 이름 형태를 보여준다.
| 구분 | 바이트 기반 스트림 | 문자 기반 스트림 | ||
| 입력 스트림 | 출력 스트림 | 입력 스트림 | 출력 스트림 | |
| 최상위 클래스 | InputStream | OutputStream | Reader | Writer |
| 하위 클래스 (예) |
XXXInputStream (FileInputStream) |
XXXOutputStream (FileOutputStream) |
XXXReader (FileReader) |
XXXWriter (FileWriter) |
InputStream과 OutputStream은 바이트 기반 입출력 스트림의 최상위 클래스이다. 이들 클래스의 하위(자식) 클래스는 모두 바이트 기반 입출력 스트림이며, 클래스 접미사로 InputStream 또는 OutputStream이 붙는다. 예를 들어 이미지와 같은 바이너리 파일의 입출력 스트림 클래스는 FileInputStream과 FileOutputStream이다.
Reader와 Writer는 문자 기반 입출력 스트림의 최상위 클래스이다. 이들 클래스의 하위(자식)클래스들은 모두 문자 기반 입출력 스트림이며, 클래스 접미사로 Reader 또는 Writer가 붙는다. 예를 들어 텍스트 파일의 입출력 스트림 클래스는 FileReader와 FileWriter이다.
바이트 출력 스트림 : OutputStream
OutputStream은 바이트 기반 출력 스트림의 최상위 클래스로 추상 클래스이다. 모든 바이트 기반 출력 스트림 클래스는 OutputStream 클래스를 상속받아 만들어진다. FileOutputStream, PrintStream, BufferedOutputStream, DataOutputStream 클래스는 모두 OutputStream 클래스를 상속하고 있다.
OutputStream 클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있다. 아래는 OutputStream 클래스의 주요 메소드이다.
| 리턴 타입 | 메소드 | 설명 |
| void | write(int b) | 1byte를 출력한다. |
| void | write(byte[] b) | 매개값으로 주어진 배열 b의 모든 바이트를 출력한다. |
| void | write(byte[] b, int off, int len) | 매개값으로 주어딘 배열 b[off]부터 len개까지의 바이트를 출력한다. |
| void | flush() | 출력 버퍼에 잔류하는 모든 바이트를 출력한다. |
| void | close() | 출력 스트림을 닫는다. |
write(int b) 메소드
write(int b) 메소드는 매개 변수로 주어지는 int(4byte)에서 끝 1byte만 출력 스트림으로 보낸다. 매개 변수가 int 타입이므로 4byte 모두를 보내는 것은 아니다.
write(byte[] b) 메소드
write(byte[] b) 메소드는 매개값으로 주어진 배열의 모든 바이트를 출력 스트림으로 보낸다.
write(byte[] b, int off, int len) 메소드
write(byte[] b, int off, int len) 메소드는 b[off]부터 len개의 바이트를 출력 스트림으로 보낸다.
바이트 입력 스트림 : InputStream
InputStream은 바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스이다. 모든 바이트 기반 입력 스트림은 InputStream 클래스를 상속받아서 만들어진다. FileInputStream, BufferedInputSteram, DataInputStream 클래스는 모두 InputStream 클래스를 상속하고 있다.
InputStream 클래스에는 바이트 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있다. 아래는 InputStream 클래스의 주요 메소드이다.
| 리턴 타입 | 메소드 | 설명 |
| int | read() | 1byte를 읽고 읽은 바이트를 리턴한다. |
| int | read(byte[] b) | 읽은 바이트를 매개값으로 주어진 배열에 저장하고 읽은 바이트 수를 리턴한다. |
| int | read(byte[] b, int off, int len) | len개의 바이트를 읽고 매개값으로 주어진 배열에서 b[off]부터 len개 까지 저장한다. 그리고 읽은 바이트 수를 리턴한다. |
| void | close() | 입력 스트림을 닫는다. |
read() 메소드
read() 메소드는 입력 스트림으로부터 1byte를 읽고 int(4byte) 타입으로 리턴한다. 따라서 리턴된 4byte 중 끝 1byte에만 데이터가 들어있다.
더 이상 입력 스트림으로부터 바이트를 읽을 수 없다면 read() 메소드는 -1을 리턴하는데, 이것을 이용하면 읽을 수 있는 마지가 바이트까지 반복해서 1byte씩 읽을 수 있다.
read(byte[] b) 메소드
read(byte[] b) 메소드는 입력 스트림으로부터 매개값으로 주어진 배열의 길이만큼 바이트를 읽고 해당 배열에 저장한다. 그리고 읽은 바이트 수를 리턴한다. 실제로 읽은 바이트 수가 배열의 길이보다 적을 경우, 읽은 수만큼만 리턴한다. 예를 들어 입력 스트림에서 5개의 바이트가 들어온다면 길이가 3인 배열로 두 번 읽을 수 있다.
read{byte[] b) 메소드 역시 입력 스트림으로부터 바이트를 더 이상 읽을 수 없다면 -1을 리턴하는데 이것을 이용하면 읽을 수 있는 마지막 바이트까지 반복해서 읽을 수 있다.
많은 양의 바이트를 읽을 때는 read(byte[] b) 메소드를 사용하는 것이 좋다. 입력 스트림으로부터 100개의 바이트가 들어온다면 read() 메소드는 100번을 반복해서읽어야 하지만, read(byte[] b) 메소드는 한 번 읽을 때 배열 길이만큼 읽기 때문에 읽는 횟수가 현저히 줄어들기 때문이다.
read(byte[] b, int off, int len) 메소드
read(byte[] b, int off, int len) 메소드는 입력 스트림으로부터 len개의 바이트만큼 읽고, 매개값으로 주어진 바이트 배열 b[off] 부터 len개까지 저장한다. 그리고 읽은 바이트 수인 len개를 리턴한다. 실제로 읽은 바이트 수가 len개보다 작은 경우에는 읽은 수만큼만 리턴한다.
read(byte[] b, int off, int len)역시 입력 스트림으로부터 바이트를 더 이상 읽을 수 없다면 -1을 리턴한다. read(byte[] b)와의 차이점은 한 번에 읽어들이는 바이트 수를 len 매개값으로 조절할 수 있고, 배열에서 저장이 시작되는 인덱스를 지정할 수 있다는 점이다. 만약 off 를 0으로, len을 배열의 길이로 준다면 read(byte[] b)와 동일하다.
문자 출력 스트림 : Writer
writer는 문자 기반 출력 스트림의 최상위 클래스로 추상 클래스이다. 모든 문자 기반 출력 스트림 클래스는 Writer 클래스를 상속받아서 만들어진다. FileWriter, BufferedWriter, PrintWriter, OutputStreamWriter 클래스는 모두 Writer 클래스를 상속하고 있다.
Writer 클래스는 모든 문자 기반 출력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있다. Wirter 클래스의 주요 메소드는 아래와 같다.
| 리턴 타입 | 메소드 | 설명 |
| void | write(int c) | 매개값으로 주어진 한 문자를 보낸다. |
| void | write(char[] cduf) | 매개값으로 주어진 배열의 모든 문자를 보낸다. |
| void | write(char[] cbuf, int off, int len) | 매개값으로 주어진 배열에서 cbuf[off]부터 len개까지의 문자를 보낸다. |
| void | write(String str) | 매개값으로 주어진 문자열을 보낸다. |
| void | write(String str, int off, int len) | 매개값으로 주어진 문자열에서 off 순번부터 len개까지의 문자를 보낸다. |
| void | flush() | 버퍼에 잔류하는 모든 문자를 출력한다. |
| void | close() | 출력 스트림을 닫는다. |
write(int c) 메소드
wirte(int c) 메소드는 매개 변수로 주어지는 int(5byte)에서 끝 2byte(1개의 문자)만 출력 스트림으로 보낸다. 매개 변수가 int 타입이므로 4byte 모두를 보내는 것은 아니다.
write(char[] cbuf) 메소드
write(char[] dbuf)메소드는 매개값으로 주어진 char[] 배열의 모든 문자를 출력 스트림으로 보낸다.
write(char[] cbuf, int off, int len) 메소드
write(char[] cbuf, int off, int len) 메소드는 c[off]부터 len개의 문자를 출력 스트림으로 보낸다.
write(String str)와 write(String str, int off, int len)메소드
Writer는 문자열을 좀 더 쉽게 보내기 위해서 write(String str)와 write(String str, int off, int len) 메소드를 제공한다. write(String str)은 문자열 전체를 출력 스트림으로 보내고, write(String str, int off, int len)은 주어진 문자열 off 순번부터 len개까지의 문자를 보낸다.
문자 입력 스트림 : Reader
Reader는 문자 기반 입력 스트림의 최상위 클래스로 추상 클래스이다. 모든 문자 기반 입력 스트림은 Reader 클래스를 상속받아 만들어진다. FileReader, BufferedReader, InputStreamReader 클래스는 모두 Reader 클래스를 상속하고 있다.
Reader 클래스에는 문자 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있다. 아래는 Reader 클래스의 주요 메소드이다.
| 리턴 타입 | 메소드 | 설명 |
| int | read() | 1개의 문자를 읽고 리턴한다. |
| int | read(char[] cbuf) | 읽은 문자들을 매개값으로 주어진 문자 배열에 저장하고 읽은 문자 수를 리턴한다. |
| int | read(char[] cbuf, int of, int len) | len개의 문자를 읽고 매개값으로 주어진 문자 배열에서 cbuf[off]부터 len개까지 저장한다. 그리고 읽은 문자 수를 리턴한다. |
| void | close() | 입력 스트림을 닫는다. |
read() 메소드
read() 메소드는 입력 스트림으로부터 1개의 문자(2byte)를 읽고 int(4byte) 타입으로 리턴한다. 따라서 리턴된 4byte 중 끝에 있는 2byte에 문자 데이터가 들어 있다. 예를 들어 입력 스트림에서 2개의 문자(총 4byte)가 들어온다면 read() 메소드로 한 문자씩 두 번 읽을 수 있다.
read() 메소드가 리턴한 int 값을 char 타입으로 변환하면 읽은 문자를 얻을 수 있다.
char charData = (char) read();
더 이상 입력 스트림으루벝 문자를 읽을 수 없다면 read() 메소드는 -1을 리턴하는데 이것을 사용하면 읽을 수 있는 마지막 문자까지 반복하면서 한 문자씩 읽을 수 있다.
read(char[] cbuf) 메소드
read(char[] cbuf) 메소드는 입력 스트림으로부터 매개값으로 주어진 문자 배열의 길이만큼 문자를 읽고 배열에 저장한다. 그리고 읽은 문자 수를 리턴한다. 실제로 읽은 문자 수가 배열의 길이보다 적을 경우 읽은 수만큼만 리턴한다. 예를 들어 입력 스트림에서 3개의 문자가 들어온다면 길이가 2인 문자 배열로 두 번 읽을 수 있다.
read(char[] cbuf) 메소드 역시 입력 스트림으로부터 문자를 더 이상 읽을 수 없다면 -1을 리턴한다. 이것을 이용하면 읽을 수 있는 마지막 문자까지 반복해서 읽을 수 있다.
많은 양의 문자를 읽을 때는 read(char[] cbuf) 메소드를 사용하는 것이 좋다. 입력 스트림으루부터 100개의 문자가 들어온다면 read() 메소드는 100번을 반복해서 읽어야 하지만, read(char[] cbuf) 메소드는 한 번 읽을 때 배열 길이만큼 읽기 때문에 읽는 횟수가 현저히 줄어든다.
read(char[] cbuf, int off, int len) 메소드
read(char[] cbuf, int off, int len) 메소드는 입력 스트림으로부터 len개의 문자만큼 읽고 매개값으로 주어진 문자 배열에서 cbuf[off] 부터 len개까지 저장한다. 그리고 읽은 문자 수인 len개를 리턴한다. 실제로 읽은 문자 수가 len개보다 적을 경우에는 읽은 수만큼 리턴한다.
read(char[] cbuf, int off, int len) 메소드 역시 입력 스트림으로부터 문자를 더 이상 읽을 수 없다면 -1을 리턴한다. read(char[] cbuf) 메소드와의 차이점은 한 번에 읽어들이는 문자 수를 len매개값으로 조절할 수 있고, 배열에서 저장이 시작되는 인덱스를 저장할 수 있다는 점이다. 만약 off를 0으로 하고, len을 배열의 길이로 준다면 read(char[] cuf) 메소드와 동일하다.
'Java' 카테고리의 다른 글
| 자바 입출력 관련 API (1) | 2023.06.30 |
|---|---|
| 자바 보조 스트림 (0) | 2023.06.30 |
| 자바 LIFO와 FIFO 컬렉션 (0) | 2023.06.29 |
| 자바 컬렉션 프레임워크 (0) | 2023.06.29 |
| 자바 스레드 제어 (0) | 2023.06.29 |