I/O1: 스트림개념, 노드스트림(파일기반 입/출력처리)
개념 및 용어정리
I/O : INPUT과 OUTPUT을 함께 일컫는 용어.
자바의 I/O : 스트림(Stream)을 이용해서 데이터를 주고받는 구조.
스트림(Stream) : 데이터의 소스에서 목적지까지 데이터를 이동시키는 일종의 통로.
- 종류 :
- 노드(Node) : 데이터의 소스나 목적지.
- 종류 : 키보드, 모니터, 파일, 메모리, DB등등
노드스트림(Node Stream) : 노드에 연결된 스트림
- 종류는 매우 다양한데 아래 3가지 조건의 조합으로 구분됨.
- 첫번째 기준 : 전송할 데이터타입이 BYTE인가? CHAR인가?
- byte(8비트)인 경우 XXStream
- char 인 경우 XXer
- byte데이터 전송인 경우 비트단위때문에 문자열이 깨지는 문제발생할수있으므로 텍스트를 전송할때는 char기반의 스트림을 사용하는 것이 좋다.
- 두번째 기준 : 데이터 이동방향
- 데이터 읽는 경우 InputStream 또는 Reader
- 데이터출력하는 경우 OutputStream 또는 write
- 세번째 기준 : 노드타입
- 단방향 중 키보드 : InputStream 또는 Reader
- 단방향 중 모니터 : OutputStream 또는 write
- 양방향 중 파일과 연결할때 : file
- 양방향 중 다른 스레드와 연결 : Piped
- 양방향 중 메모리와 연결 : Array(ByteArray, CharArray)
I/O클래스의 구조
InputStream / OutputStream (바이트 입출력)
Reader / Writer (문자 입출력)
노드스트림
- 모든 스트림은 노드 스트림에서 시작.
- 노드 스트림의 최상위 인터페이스 : InputStream과 Reader, OutputStream과 write
키보드를 이용한 InputStream과 Reader
- read()메서드는 스트림에서 데이터를 읽음.
- return byte의 개수.
- return -1이면 더이상 읽을 데이터가 없음을 의미.
- 전송될 데이터가 숫자인 경우 byte단위의 InputStream사용 추천
- 전송될 데이터가 문자인 경우(특히 한글) char단위의 Reader사용 추천
키보드를 이용한 InputStream 예시
- buffer : 데이터를 한 번에 읽을 수 있기위해 생성한 배열.
- read(byte[]), read(byte[], int, int) : 버퍼단위로 데이터를 읽음.
- 한계 : InputStream은 byte단위의 전송때문에 한글자가 2byte이상인 한글은 깨짐 => Reader사용
1 | System.out.println("입력하세요"); |
키보드를 이용한 Reader 예시
1 | char[] buffer = new char[10]; |
모니터를 이용한 OutputStream과 Writer
- Write는 OutputStream의 byte가 char로 대체된다.
OutputStream사용
- getBytes()를 이용하여 byte[]로 바꾼 뒤 write()로 출력하면 된다.
1
2
3
4
5
6
7
8try(OutputStream os = System.out){
String msg = "안녕 월요일";
os.write(msg.getBytes());
}catch(IOException e){
e.printStackTrace();
}
//출력값
안녕 월요일
Writer사용
- byte를 char단위로 바꾸기 위해 OutputStreamWriter를 사용하여 Writer생성한다.
1
2
3
4
5
6
7
8
9try(Writer wr = new OutputStreamWriter(System.out)){
String msg = "안녕";
wr.write(msg);
wr.append("피곤한").append("월요일");
}catch(IOException e){
e.printStackTrace();
}
//출력값
안녕피곤한월요일
메모리기반 입/출력처리
- CharArrayReader가 변수 memory를 buffer만큼 읽고 CharArrayWriter에 출력한다.
- CharArrayWriter에 출려된 내용을 모니터에 출력(System.out.println)한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14char[] memory = "안녕 또다시 월요일".toCharArray();
char[] buffer = new char[5];
int read=0;
try(CharArrayReader car = new CharArrayReader(memory);
CharArrayWriter caw = new CharArrayWriter();){
while((read=car.read(buffer)) > 0){
caw.write(buffer, 0, read);
}
System.out.println(Arrays.toString(caw.toCharArray()));
}catch(IOException e){
e.printStackTrace();
}
//출력값
[안, 녕, , 또, 다, 시, , 월, 요, 일]
파일기반 입/출력처리
- 가장 빈번히 사용하며 너무나도 중요해서 아래 게시글에 별도로 포스팅을 했다.
- 링크 : 노드스트림 - 파일기반 입/출력처리
다른 스레드와의 통신을 위한 스트림
- 스레드간의 통신을 위해서는 PipedInputStream/PipedOutputStream 이나 PipedReader/PipedWriter가 사용됨.
- 다른 스트림과 공통점 : 데이터 읽고 쓰는 과정.
- 다른 스트림과 차이점 : 사용 전 connect()메서드를 사용하여 연결 필수!