My Profile Photo

DongChanS's blog


수학과 학생의 개발일지


Java (9) - File IO (2) - Auxiliary Stream

1) Auxiliary Stream (보조 스트림)

보조스트림은 Node(출발지, 목적지)와 연결되는게 아니라, 스트림과 스트림 사이를 잇는 역할을 합니다.

1-1. 보조 스트림의 기능

  1. byte Stream -> Char Stream

    • InputStreamReader : InputStream -> Reader
    • OutputStreamWriter : OutputStream -> Writer
  2. 속도향상

    • Buffered +

      (Reader, Writer, InputStream, OutputStream)

  3. Primitive data type 전송

    • Data(Input/Output)Stream
  4. Object 전송

    • Object(Input/Output)Stream
  5. 문자열 표현으로 출력하기

    • PrintWriter
    • PrintStream

1-2. 보조 스트림의 생성

그냥 앞단계의 스트림을 생성자에 넣어주면 됩니다.

사용예시)

BufferedInputStream bis = new BufferedInputStream(System.in);
DataInputStream dis = new DataInputStream(bis);
  • System.in : 키보드 (노드 스트림)

    +속도 향상 (bis)

    +데이터 전송 기능 추가 (dis)

1-3. byte Stream -> Char Stream

  • 키보드(System.in)나, 모니터(System.out)는 기본적으로 byte형태를 선호함.

    그러나, byte형태는 보기가 어려운 경우가 많음

  • 그래서 byte 값을 몇개 뭉쳐서 char형태로 바꿔주어야 합니다. (디코딩)

    (반대로 char형태를 byte값으로 분해하는 것을 인코딩이라 합니다.)

  • 인코딩, 디코딩에는 여러 종류가 있는데,

    byte 값들을 문자로 맵핑시키는 방식이 각각 다르기 떼문입니다.

    대표적으로 utf-8 인코딩 방식이 많이 쓰입니다.

사용예시)

public class InputStreamReaderTest {
    public static void main(String[] args) throws IOException {
        InputStream is = System.in; 
        // 어자피 System.in 그자체가 스트림이니까 굳이 이렇게까지는 안해도됨.
        InputStreamReader isr = new InputStreamReader(is);
        char[] cbuf = new char[4];
        isr.read(cbuf);
        for (char c:cbuf){
            System.out.println(c);
        }
    }
}
1abc (입력)
1
a
b
c
  • isr.read(cbuf) : char형태의 배열에 읽어들인 값을 저장한다.

1-4. 버퍼링을 통한 속도 향상

  • 버퍼링

    1

    • 파일이나 네트워크 너머에 있는 데이터(ex 동영상)을 직접 프로그램에서 읽어들여서 처리하면 비효율적임

    • 메모리(버퍼)에 임시로 저장하고, 메모리에 있는 파일을 프로그램에서 처리하는게 효율적 : 버퍼링

      (디스크보다는 메모리에 빠르게 접근할 수 있기 때문)

  • (Java) 보조 스트림을 이용한 버퍼링

    • Buffered +

      (Reader, Writer, InputStream, OutputStream)을 이용하면 간단하게 해결가능!

    • 기본적으로 8192의 버퍼크기를 가지고 있음.

  • Scanner는 내부적으로 1024의 버퍼를 통해서 구현이 되는데, 그러다보니 BufferedReader 를 이용해서 데이터를 받는 것 보다 상당히 느립니다.

    (한번에 적은 양만 받을 수 있으니까 많이 데이터를 왔다갔다 해야하므로..)

1-5. 버퍼링을 이용해서 알고리즘 문제 풀기

그러면 위에서 배웠던 I/O 이론을 이용해서 알고리즘 문제(빠른 A+B)를 풀어봅시다.

그냥 1111 2222라는 문자열을 받으면 띄어쓰기 기준으로 합쳐서 3333을 출력하면 되는 간단한 문제인데요..

자바에서는 I/O를 이해하지 않으면 어려운 문제입니다.

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    static int T, t1, t2;
    static String str;

    public static void main(String[] args) throws IOException {
        // input 을 빠르게 받기 위한 장치
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        // 빠르게 출력하기 위한 장치
        OutputStream os = System.out;
        OutputStreamWriter osw = new OutputStreamWriter(os);
        BufferedWriter bw = new BufferedWriter(osw);

        // input 받고 출력하기
        T = Integer.parseInt(br.readLine());
        for (int i=0; i<T; i++){
            str = br.readLine();
            StringTokenizer st = new StringTokenizer(str);
            t1 = Integer.parseInt(st.nextToken());
            t2 = Integer.parseInt(st.nextToken());
            str = (t1 + t2) + "\n";
            bw.write(str);
        }
        bw.flush();
    }
}

  • System.in (byte) -> InputStreamReader (byte -> Char) -> BufferedReader (Char -> buffering)

  • System.out (byte) -> OutputStreamWriter (byte -> Char) -> BufferedWriter (Char -> buffering)

  • StringTokenizer : 주어진 string을 토큰 단위로 분리할 수 있는 클래스

    • 토큰 단위(delimeter) : 띄어쓰기(' '), 파라미터로 조절 가능

    • st.nextToken() : 다음 토큰을 획득

    ex) "1111 2222" -> "1111" & "2222"

  • Integer : 정수(primitive data type)을 객체화시킨 Wrapper 클래스

    • Integer.parseInt(string) : string을 정수로 바꿈.
  • (t1 + t1) + '\n' : 개행문자 추가 + String으로 형변환

  • bw.write(string) : string을 버퍼에 기록함.

    bw.flush() : 버퍼의 내용을 출력하고 버퍼를 비운다.

만약 테스트를 위해서 텍스트파일을 사용하고 싶다면,

System.in 대신에 텍스트파일의 값을 받을 수 있는 파일스트림을 추가해주면 됩니다.

String path = "baekjoon" + File.separator + "15552_input.txt";
File f = new File(path);
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis);

그다음에는 객체나 원시 데이터를 처리하는 보조 스트림들이 있긴한데..

일단 현 상황에는 크게 중요해보이지 않아서 다루지 않겠습니다.

comments powered by Disqus