InputStream
InputStream 의 정의는
This abstract class is the superclass of all classes representing an input stream of bytes.
이 추상 클래스는 바이트의 입력 스트림을 나타내는 모든 클래스의 슈퍼 클래스입니다.
여기서 중요한건 "바이트 입력 스트림"이다.
byte 란?
하나의 단위로서 다루는 비트(bit)의 모임. 8비트의 모임을 1바이트라고 한다.
Stream 이란?
Stream in java
A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result.스트림(Stream)은 원하는 결과를 생성하기 위해 파이프라인화될 수 있는 다양한 방법을 지원하는 객체의 연속이다.
Stream은 데이터의 이동 통로라고 해석할 수 있다.
즉, InputStream 데이터를 byte 단위로 입력하는 통로이고 , OutputStream은 출력 통로이다.
InputStream (System.in) / System.in은 무엇인가?
Scanner sc = new Scanner(System.in);
System Class의 in은 InputStream Type 이다. 즉, System.in 이 InputStream 타입의 필드이다.
*System 클래스 in 변수는 '표준 입력 스트림'이며 일반적으로 콘솔, 명령줄 인수 등을 통해 입력을 받다. 키보드, 터미널 등에서 입력을 넣어주는 것들을 System.in 을 통해 연결된다는 의미
테스트 해보자
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) throws IOException {
InputStream inputstream = System.in;
int a = inputstream.read();
System.out.println(a);
}
}
1을 입력하면
12를 입력하면
결과가 49로 같은 값이 나온다.
이유는 InputStream은 1바이트 단위로 입력받는다. 그래서 1의 아스키코드 값인 49, 12에서 첫 1바이트 값인 1의 아스키코드 값인 49가 나오게 된다.
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) throws IOException {
InputStream inputstream = System.in;
int a = inputstream.read();
System.out.println(a);
int b = inputstream.read();
System.out.println(b);
}
}
이렇게 b를 추가해 값을 읽어주면
1,2 각각의 아스키코드값이 나온다.
만약 n개의 문자를 입력받고 싶으면 n개의 변수를 선언해야하나 싶겠지만, 바이트 타입 배열로 선언해 read()메소드에 넣어서 입력받는 방법도 있다.
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) throws IOException {
InputStream inputstream = System.in;
byte[] a = new byte[2];
inputstream.read(a);
for(byte val : a){
System.out.println(val);
}
}
}
결과는 위에 2개의 변수를 선언한 값과 같다.
Scanner
주로 아래와 같이 사용하는데
Scanner sc = new Scanner(System.in)
오버리이딩 된 Scanner 를 보면
InputStream을 통해 입력된다.
자세히 보면 Scanner() 생성자들이 this를 통해서 private Scanner(Readable source, Pattern pattern) 으로 넘겨진다.
여기서 InputStreamReader가 나온다.
InputStreamReader이란?
An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset. The charset that it uses may be specified by name or may be given explicitly, or the platform's default charset may be accepted.
InputStreamReader는 **"바이트 스트림에서 문자 스트림으로의 브리지" **입니다. 바이트를 읽고 지정된 문자 집합을 사용하여 바이트를 문자로 디코딩합니다. 사용하는 문자 집합은 이름으로 지정되거나 명시적으로 지정되거나 플랫폼의 기본 문자 집합이 허용될 수 있습니다.
전에 알아본 InputStream에서 1Byte씩 받은 문자를 문자단위인 character로 변환시키는 중개자 이다. 문자스트림이라고 불리기도 한다.
InputStream 은 Byte Type, 바이트 단위
InputStreamReader 은 char Type, 문자 단위
추가로, Scanner 가 느리다고 많이들 얘기하는데 느린 이유는 Scanner는 수많은 정규식을 통해 검사 된 문자열을 반환하기 때문에 느려진다. 정규식 자체도 느리지만 정규식의 양이 많다.
BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
위에서 정리한게 이해됐다면 BufferedReader 도 금방 이해가 가능할거라 생각된다.
BufferedReader를 선언할 때 new BufferedReader(new InputStreamReader(System.in)) 를 사용한다.
즉, BufferedReader는 문자를 받는다.
우리는 문자열을 입력할때 문자열의 길이가 가변적이다. 그래서 Buffer(버퍼)를 통해 입력받은 문자를 쌓아둔 뒤 한 번에 문자열처럼 보내버린다.
BufferedReader의 입력 메소드로 readLine()을 많이 쓴다. 이 메소드는 한 줄 전체(공백 포함)를 읽기 때문에 char 배열을 하나하나 생성할 필요 없이 String 으로 리턴하여 바로 받을 수 있다는 장점을 가지고 있다.
즉, 문자를 가변적으로 받아 문자의 직렬화를 통해 문자열을 만들게 된다.
정리하면,
System.in -> InputStream -> InputStreamReader -> BufferedReader
입력 -> Byte type -> char type -> String
또한 BufferedReader는 따로 정규식 검사를 진행하지 않고, 버퍼에 저장해 String을 만든다.
그래서 Scanner에 비해 성능이 좋다.
가볍게 정리해보면
Scanner 에서 InputStreamReader 를 사용하는 이유는 문자를 온전하게 받기 위함이고
Scanner의 메소드 next(), nextInt() 등은 타입에 맞게 정규식을 검사해서 상대적으로 느리다
Reference
'Java' 카테고리의 다른 글
[Java]문자열 자르기 (0) | 2022.08.09 |
---|---|
[Java] EOF 처리 (0) | 2022.08.05 |
[Java] java의 인코딩 Unicode, UTF-8, EUC-KR (0) | 2022.07.22 |
[Java] java의 인코딩 ASCII Code, Extend ASCII Code (0) | 2022.07.19 |
[Java] 람다식 (0) | 2022.06.03 |
댓글