본문 바로가기

Java/information

[자바/JAVA] Stream

프로그램은 데이터를 읽고 출력하는 작업을 빈번히 수행한다.
데이터는 키보드를 통해 입력될 수도 있고, 파일 또는 네트워크로부터 입력될 수도 있다.
반대로 모니터로 출력될 수도 잇고, 파일 또는 네트워크로 출력될 수도 있다.

 

자바에서 데이터는 스트림을 통해 입출력 된다. 스트림은 단일 방향으로 연속적으로 흘러가는 것을 말하는데,
물이 높은 곳에서 낮은 곳으로 흐르듯이 데이터는 출발지에서 도착지로 흘러간다.
프로그램이 출발지냐 또는 도착지냐에 따라서 사용하는 스트림의 종류가 결정된다.
프로그램이 도착지이면 흘러온 데이터를 입력받아야 하므로 입력 스트림을 사용하고, 반대로 프로그램이 출발지면 데이터를 출력해야 하므로 출력 스트림을 사용한다.

입출력 스트림의 종류


java.io 패키지에는 여러 가지 종류의 스트림 클래스를 제공한다. 
이들 스트림 클래스를 크게 두 종류로 구분한다.
-바이트 기반 스트림 : 그림, 멀티미디어 등의 바이너리 데이터를 읽고 출력할 때 사용
-문자 기반 스트림 : 문자 데이터를 읽고 출력할 때 사용

스트림 클래스가 바이트 기반인지, 문자 기반인지를 구별하려면 최상위 클래스를 보면 된다.

스트림
-데이터가 다니는 길(컴퓨터와 입출력 장치 사이에 연결된 길)
-크게 구분
1)바이트 단위 입출력 클래스 - 클래스명이 Stream으로 끝나는 클래스
2)문자 단위 입출력 클래스 - 클래스명이 Reader/Writer로 끝나는 클래스
-구분
1)입력 스트림 클래스 - 클래스명이 InputStream 또는 Reader로 끝남
2)출력 스트림 클래스 - 클래스명이 OutputStream 또는 Write로 끝남

InputStream과 OutputStream은 바이트 기반 입출력 스트림의 최상위 클래스이다.
이들 클래스의 하위(자식)클래스는 모두 바이트 기반 입출력 스트림이며, 클래스 접미사로 InputStream 또는 OutputStream이 붙는다.
예를 들어 이미지와 같은 바이너리 파일의 입출력 스트림 클래스는 FileInputStream과 FileOutputStream이다.

InputStream클래스에는 바이트 기반 입력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있다. 주요 메소드로는 read(), read(byte[] b), read(byte[] b, int off, int len), close()등이 있다. 
read()메소드는 입력 스트림으로부터 1바이트를 읽고 4바이트 int타입으로 리턴하는데 리턴된 4바이트 중의 끝의 1바이트에만 데이터가 들어가 있다. 
더이상 바이트를 읽을 수 없다면 -1을 리턴하는데 이것을 이용하면 읽을 수 있는 마지막 바이트까지 루프를 돌며 한바이트씩 읽을 수 있다.
InputStream을 더이상 사용하지 않을 경우에는 close()를 호출해서 사용했던 시스템 자원을 풀어준다.
read(byte[] b) 역시 바이트 기반 입력 스트림의 메소드로 입력 스트림으로부터 매개값으로 주어진 바이트배열의 길이만큼 바이트를 읽고 배열에 저장한다. 
그리고 읽은 바이트 수를 리턴한다. 실제로 읽은 바이트 수가 배열의 길이보다 작을 경우 읽은 수만큼 리턴한다.
ex)read(byte[] 3)은 입력 스트림에서 5개의 바이트가 들어오면 길이 3인 배열로 한 번 읽고 두번째로 남은 바이트 2개를 읽은 후 2를 리턴하고, 6개의 바이트가 들어오면 3인 배열로 두번 읽고 바이트를 더이상 읽을 수 없다면 -1을 리턴한다.

read(byte[] b, int off, int len): 역시 바이트 기반 입력 스트림의 메소드로 입력 스트림으로부터 매개값으로 주어진 바이트배열의 길이에서 len개의 바이트값만큼 읽고, 매개값으로 주어진 바이트 배열 b[off]부터 len개까지 저장한다. 
그리고 읽은 바이트 수인 len개를 리턴한다. 실제로 읽은 바이트 수가 배열의 길이보다 작은 경우 읽은 수 만큼 리턴한다. 
ex) 5개의 바이트가 들어오고 여기서 3개만 읽어 b[2], b[3], b[4]에 각각 저장한다면 read(byte[] b, 2, 3)으로 호출할 수 있다. 더이상 읽을 수 없다면 -1을 리턴한다.
read(byte[] b)와의 차이점은 한번에 읽어들이는 바이트 수를 len 매개값으로 조절할 수 있고, 배열에서 저장이 시작되는 인덱스를 저장할 수 있다는 점이다. 만약 off를 0으로, len을 배열의 길이로 준다면 read(byte[] b)와 같은 결과가 된다.

바이트 기반 출력 스트림의 최상위 클래스는 OutputStream으로 추상 클래스이다.
OutputStream클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져야 할 메소드가 정의되어 있다. 
주요 메소드 write(int b), write(byte[] b), write(byte[] b, int off, int len), flush(), close() 등이 있다.
write(int b)는 매개변수로 주어진 정수 값에서 끝에 있는 1바이트만 출력 스트림으로 보낸다. 

네트워크로 문자열을 전송하거나 문자열을 암호화할 때 등 문자열을 바이트 배열로 변환하는 경우가 있는데 "문자열".getBytes()는 문자열을 바이트 형태 배열로 변환하며 시스템의 기본 문자 set으로 인토딩된 바이트 배열을 리턴한다. 
원하는 문제 set으로 인코딩하고 싶을 때 매개변수로 EUC-KR, UTF-8을 넣을 수 있으며 EUC-KR은 기본 매개변수 없을 때와 마찬가지로 알파벳은 1바이트, 한글은 2바이트로 변환하고 UTF-8은 알파벳은 1바이트, 한글은 3바이트로 변환한다. 
출력 스트림은 내부에 작은 버퍼가 있어서 데이터가 출력되기 전에 버퍼에 쌓여있다가 순서대로 출력된다. 
flush()메소드는 버퍼에 잔류하는 데이터를 모두 출력시킨 후 버퍼를 비우는 역할을 한다. 
프로그램에서 더 이상 출력할 데이터가 없다면 flush()메소드를 마지막으로 호출하여 모든 데이터가 출력하게 해준후 OutputStream을 더이상 사용하지 않을 경우 close()를 호출해서 사용했던 시스템 자원을 풀어준다. 

문자 기반 입력 스트림의 최상위 클래스는 Reader로 추상 클래스이다. FileReader, BufferedReader, InputStreamFeader 클래스는 모두 이 클래스를 상속받고 있다. 
Reader클래스에는 문자 입력 스트림이 기본적으로 가져야 할 메소드가 정의되고 있다. read(), read(char[] cbuf), read(char[] cbuf, int off, int len), close() 등이 있다.
read()는 입력 스트림으로부터 한개의 문자를 2바이트로 읽고 4바이트 int타입으로 리턴한다. 따라서 리턴된 4바이트 중 끝에 있는 2바이트에 문자 데이터가 들어있다.
 ex)입력 스트림에서 5개의 문자 (총 10바이트)가 들어온다면 read()메소드로 한문자씩 다섯번 읽을 수 있다. read()가 리턴한 정수값을 char타입으로 변환하면 문자를 얻을 수 있다.
 
read(char[] cbuf)는 매개값으로 주어진 문자 배열의 길이만큼 문자를 읽고 배열에 저장한다. 
읽은 문자 수를 리턴한다. 실제로 읽은 문자수가 배열 길이보다 작을 경우 읽은 수만큼 리턴한다. 
ex)스트림에서 새개의 문자가 들어온다면 길이가 2인 문자배열로 두번 읽을 수 있다.
 
read(char[] cbuf, int off, int len)는 입력 스트림으로부터 len개의 문자만큼 읽고 매개값으로 주어진 문자 배열 cbuf[off]부터 len개까지 저장한다. 읽은 문자수인 len개를 리턴한다.
ex)전체 3개의 문자가 들어오고 여기서 2개만 읽고 cbuf[1],cbuf[2]에 각각 저장한다면 read(char[] cbuf, 1, 2)를 호출하면 된다. read(char[] cbuf)와의 차이점은 한번에 읽어들이는 문자수를 len 매개값으로 조절할 수 있고, 
배열에서 읽어들이는 인덱스를 지정할 수 있다는 점이다. 만약 off를 0으로 주고, len을 배열의 길이와 동일하게 준다면 동일한 결과값을 얻는다.

Reader와 Writer는 문자 기반 입출력 스트림의 최상위 클래스이다. 이들 클래스의 하위(자식)클래스들은 모두 문자 기반 입출력 스트림이며, 
클래스 접미사로 Reader 또는 Writer가 붙는다. 예를 들어 텍스트 파일의 입출력 스트림 클래스는 FileReader와 FileWriter이다.

표준 입출력 클래스
-표준 입력 - 키보드로부터 데이터를 입력받는 것

Scanner 클래스
-Scanner 클래스를 이용하면 표준 입력을 쉽게 해결
-java.util 패키지에 있고, 다양한 자료형을 읽어올 수 있는 메소드들이 있어 다양한 데이터 입출력을 처리하는데 유용

자바는 콘솔로부터 데이터를 입력받을 수 있도록 System 클래스의 in 정적 필드를 제공하고 있다. 
콘솔에 데이터를 입력받을 때 System.in을 사용하고, 콘솔에 데이터를 출력할 때 System.out을 사용하는데 system.in은 InputStream 타입의 필드이므로 InputStream 변수로 참조가 가능하다. =>InputStream is = System.in;

키보드로부터 어떤 키가 입력되었는지 확인하려면 InputStream의 read()메소드로 한 바이트를 읽는다. 리턴된 int값에는 십진수 아스키 코드가 들어있다.

'Java > information' 카테고리의 다른 글

[자바/JAVA] generic  (0) 2023.06.01
[자바/JAVA] 보조 스트림  (0) 2023.05.30
[자바/JAVA] java.util의 여러 클래스들  (0) 2023.05.23
[자바/JAVA] API와 String 메소드들  (0) 2023.05.19
[자바/JAVA] 예외 클래스  (0) 2023.05.17