1) Auxiliary Stream (보조 스트림)
보조스트림은 Node(출발지, 목적지)와 연결되는게 아니라, 스트림과 스트림 사이를 잇는 역할을 합니다.
1-1. 보조 스트림의 기능
-
byte Stream -> Char Stream
- InputStreamReader : InputStream -> Reader
- OutputStreamWriter : OutputStream -> Writer
-
속도향상
-
Buffered +
(Reader, Writer, InputStream, OutputStream)
-
-
Primitive data type 전송
- Data(Input/Output)Stream
-
Object 전송
- Object(Input/Output)Stream
-
문자열 표현으로 출력하기
- 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. 버퍼링을 통한 속도 향상
-
버퍼링
-
파일이나 네트워크 너머에 있는 데이터(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);
그다음에는 객체나 원시 데이터를 처리하는 보조 스트림들이 있긴한데..
일단 현 상황에는 크게 중요해보이지 않아서 다루지 않겠습니다.