I/O1: 스트림개념, 노드스트림(파일기반 입/출력처리)

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클래스의 구조
    https://estindev.tistory.com/entry/%EC%9E%90%EB%B0%94-IO-%EC%A0%95%EB%A6%AC

  • InputStream / OutputStream (바이트 입출력)
    https://hyeonstorage.tistory.com/250

  • Reader / Writer (문자 입출력)
    https://hyeonstorage.tistory.com/250




노드스트림

  • 모든 스트림은 노드 스트림에서 시작.
  • 노드 스트림의 최상위 인터페이스 : 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
System.out.println("입력하세요");
byte[] buffer = new byte[10];
try(InputStream input = System.in){
int read = -1;
while((read = input.read(buffer)) > 0){
System.out.println("읽은 값: "+read+", 문자열로: "+ new String(buffer, 0, read));
}
}catch(IOException e){
e.printStackTrace();
}
//입력값
자바는 객체지향 언어입니다
//출력값
읽은 값: 10, 문자열로: 자바는 객?
읽은 값: 10, 문자열로: 셉置? 언어
읽은 값: 8, 문자열로: 입니다




키보드를 이용한 Reader 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char[] buffer = new char[10];
try(Reader rd = new InputStreamReader(System.in)){
int read =-1;
while((read = rd.read(buffer)) > 0){
System.out.println("읽은 값: "+read+", 문자열로: "+ new String(buffer, 0, read));
}
}catch(IOException e){
e.printStackTrace();
}
//입력값
자바는 객체지향 언어입니다
//출력값
읽은 값: 10, 문자열로: 자바는 객체지향 언
읽은 값: 6, 문자열로: 어입니다




모니터를 이용한 OutputStream과 Writer

  • Write는 OutputStream의 byte가 char로 대체된다.




OutputStream사용

  • getBytes()를 이용하여 byte[]로 바꾼 뒤 write()로 출력하면 된다.
    1
    2
    3
    4
    5
    6
    7
    8
    try(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
    9
    try(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
    14
    char[] 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()메서드를 사용하여 연결 필수!