요약
1. 자바 입력의 전체적 개요
2. UTF-8 과 UTF-16 의 구성 방식의 차이
3. Stream
4. System.in
5. InputStreamReader
6. Scanner(System.in)
7. BufferedReader
자바 입력의 전체적 개요
- 자바는 문자열을 메모리 상에서 UTF-16으로 인코딩하여 처리.
- 문자열 송/수신을 위해 직렬화가 필요할 때에는 변형된 UTF-8 을 사용.
- 문자열을 입출력 할 때는 운영체제 기본 인코딩값,
또는 사용자가 지정한 인코딩 값(file encoding)으로 문자열을 인코딩.
(메모리 상에서 처리되는 것과는 다름.)
- 1 ~ 127 까지는 아스키 코드 값과 유니코드(UTF-8, UTF-16 등 ), MS계열 코드(CP949, MS949 등 ) 의 값이 같다.
위의 항목 3가지를 쉽게 표시하면 아래와 같다.
입력(UTF-8) -> 송수신(modified UTF-8) -> 자바 메모리 (UTF-16) -> 송수신(modified UTF-8) -> 출력(UTF-8)
마지막 4번째 항목의 말은
해당 값과 아스키 코드 값이 10진수로 1~127 번까지는 대응되는 문자가 같다. 라는 말이다.
char -> int 로 값을 반환할 때 나오는 값도 아스키 코드 값이 아니라
정확히는 파일 인코딩 형식의 10진수 값이 나온다.
(127 번째 문자까지는 대응되는 문자들이 같기 떄문에 아스키코드값이라도 말해도 무방한 것.)
UTF-8 과 UTF-16 의 구성 방식의 차이
UTF-8 : 영어의 경우 1Byte, 한글의 경우 3Byte 를 사용
UTF-16 : 거의 모든 문자가 2Byte 로 구성
1. Stream
A에서 B로의 데이터의 흐름 자체를 말한다.
데이터 고속도로 같은 것이랄까.
고로 한 방향으로 밖에 이동이 안된다.
이 방향이 입력이 되면 InputStream
출력이 되면 OutputStream
이 된다.
Stream은 모두 바이트 단위로 데이터를 전송한다.
2. System.in
System 클래스의 in 이라는 변수는 사실 InputStream의 Static 변수다.
따라서 InputStream 타입으로 변수 a를 선언 후에 System.in을 넣을 수 있다는 말이다.
InputStream.read()는 1byte단위로만 읽는다.
그래서 a를 읽으면 1byte의 인코딩 형식의 10진수 값 (위에서 말했듯)으로 결과가 나온다.
위와 똑같은 내용으로 짰고
1을 입력한 후 49라는 결과를 받은
아래의 예를 보자.
package LectureExam;
import java.io.IOException;
import java.io.InputStream;
public class exercise1 {
public static void main(String[] args) throws IOException {
InputStream inputstream = System.in;
int a = inputstream.read();
System.out.println(a);
}
}
결과
1
49
3. InputStreamReader
InputStreamReader와 InputStream의 차이를 알아보자면
InputStream는
- 1byte 씩 밖에 읽지 못한다.
- int 형으로 10진수의 UTF-16 값으로 저장된다.
그럼 저 단점을 보완하기 위해 개발된 녀석일 것이다.
특징은 아래와 같다.
- 바이트 단위 데이터를 문자(character) 단위 데이터로 처리할 수 있도록 변환해준다.
- char 배열로 데이터를 받을 수 있다.
4. Scanner(System.in)
아래는 Scanner의 클래스다.
Scanner 의 클래스를 보면 수많은 메소드가 오버로딩이 되어있다.
그리고 우리가 자주 쓰는 Scanner(System.in)는
public Scanner(InputStream source) {
this(new InputStreamReader(source), WHITESPACE_PATTERN);
}
여기에 해당한다.
자 익숙한 친구가 보인다.
InputStreamReader 이 친구가 Scanner의 주요 변환계인 것이다.
이후 더 파고 들어가면 Scanner는 뭘 검사하는 게 많다...
그래서 느리고 무겁다. 하지만 형변환을 함에 있어 안정성은 굉장히 높다.
고로, Scanner의 메카니즘은 다음과 같다.
InputStream 로 입력 (int 타입)
=> InputStreamReader을 통해 편하게 데이터 처리 (char 타입)
=> 입력문자는 입력 메소드( next(), nextInt() 등) 타입에 맞게 정규식을 검사
=> 정규식 문자열을 Pattern.compile() 메소드로 Pattern 타입으로 변환
=> Pattern 타입을 String으로 변환
=> String 을 입력 메소드의 타입에 맞게 반환 ( nextInt() - Integer.parseInt() 등 )
5. BufferedReader
아래는 BufferedReader를 사용할 때 보통 쓰는 형식의 구문이다.
BufferedReader aaa = new BufferedReader(new InputStreamReader(System.in));
System.in => byte로만 받을 수 있는 InputStream 을
InputStreamReader => char로 받을 수 있게 하고
BufferedReader로 받는다.
그렇다.
BufferedReader는
Buffer에 문자열을 한꺼번에 담은 다음 한번에 보내버린다.
String과 다름없이 처리한다는 말.
게다가 딱히 검사하는 식도 없다.
Buffer를 활용하고
검사식이 없으니
Scanner 보다 압도적으로 빠르다.
BufferedReader (버퍼를 이용한 입력)란?
(7/22 Scanner 클래스와 비교하면서 볼 것)
- 이름처럼 버퍼를 이용해서 작업을 하는 클래스
- 띄어쓰기와 엔터를 경계로 입력값을 인식받는 Scanner와는 다르게
엔터만 경계로 인식하고 받는 데이터도 String으로 고정되기 때문에 데이터를 따로 가공을 해야한다는 불편함이 있다.
하지만 Scanner보다 훨씬 빠르다.
- 많은 데이터를 입력받아야하는 상황에서 좋다.
- 사용법은 Scanner와 동일하다.
BufferedReader 메소드 종류
Type | Method | 설명 |
void | close() | InputStream을 닫고 사용하던 자원들을 푼다 |
void | mark( int, readAheadLimit ) | Stream의 현재 위치를 마킹 |
boolean | markSupported() | Stream이 mark를 지원하는 지 true / false로 알려줌. |
int | read() | 한 글자만 char로 읽어서 정수형으로 변환한다. ex) 5를 읽으면 '5'을 읽어서 int로 변환한 53을 반환한다. => 아스키값을 가져온다는 말 |
int | read( char a, int b, int c ) | a를 b위치부터 c정도의 길이만큼 문자를 스트림으로부터 읽어온다. |
String | readLine() | 한 줄로 읽고 String으로 반환한다. |
boolean | ready() | InputStream이 준비 되었는지 확인. 1이라면 준비완료. |
void | reset() | 마킹이 있으면 해당 위치부터 시작. 그게 아니면 처음부터 시작. |
long | skip( long n ) | n개의 문자를 건너 뛴다. |
'자바(Java) > 자바(Java) 잡다' 카테고리의 다른 글
자바(Java) PriorityQueue (0) | 2023.02.26 |
---|---|
자바(Java) StringTokenizer 클래스과 split 메소드 (0) | 2023.02.20 |
자바(Java) StringBuilder와 String (0) | 2023.02.09 |
자바(Java) Arrays.sort()와 Collections.sort() (0) | 2023.02.09 |
자바(Java) Iterator와 hasNext() / next() / remove() (0) | 2023.02.02 |
댓글