Java 입출력 과 스트림

한호성·2022년 5월 11일

JAVA 인코딩 방식

1. 자바는 메모리 상에  UTF-16 으로 인코딩 되어 처리
2. 문자열 송/수신을 위해 직렬화 할 때에는 UTF-8 사용
3. 문자열을 입출력 할 떄는, 운영체제 기본 인코딩 값  
사용자 지정 인코딩 값으로 문자열을 인코딩한다 -> 메모리상에서 처리되는 것과는 다르다.

IDE 입출력이 UTF-8 이라고 가정하면,

결론 : 
입력(UTF-8) -> 송수신 (Modified UTF-8) ->
자바 메모리(UTF-16) -> 송수신(Modified UTF-8) ->
출력( UTF-8) 순서로 인코딩,디코딩이 진행된다

* Char에 문자를 저장하여 int 값으로 변환할 때 ASCII Code 값으로 변환한다 
라고 생각하는 경우가 많지만, 이는 1~127번째 문자까지만 해당하는 말이고, 정확히는 
"파일 인코딩 형식" 의 10진수 값이 나온다고 하는 것이 올바른 말이다.  

입력 관련 class들에 대해 알아보자


Scanner scan = new Scanner(System.in);
BufferedReaeder br =new BufferedReader (new InputStreamReader(System.in));

원시 입력방법 -> 확장되는 class 개념으로 설명진행 해보자.

  • Stream 기본개념
  • InputStream, Systme.in
  • Scanner(System.in), InputStreamReader()
  • BufferedReader()

1.Stream

: 스트림은 한 곳에서 다른곳으로의 데이터의 흐름을 의미한다
(출발지 와 도착지를 이어주는 역할)

  • 파일 데이터 (시작과 끝이 있는 데이터의 스트림)
  • HTTP 응답 데이터 (브라우저 response-request 도 스트림)
  • 키보드 입력 (사용자 키보드 입력하는 문자열도 스트림)

스트림은 단반향이기 때문에, 입력과 출력이 동시에 발생할 수 없다. 그렇기 때문에 용도에 따라 입력스트림 출력스트림이 나뉜다.

-아래의그림을 보면 Stream 에 대한 이해가 가능하다.

2.InputStream

자바에서 가장 기본이 되는 입력스트림은 InputStream 이고, 출력스트림은 OutputStream 이다.

System.in 과 inputStream 의 관계

System 클래스의 in 이라는 필드가(멤버변수) 존재하고 이는 InputStream의 정적 필드이다.

InputStream 은 가장 기본적인 입력스트림 -> 이 말의 의미를 생각해보자

InputStream.read() 의 특징

  • 입력받은 데이터는 int 형으로 저장되는데, 시스템 또는 운영체제의 인코딩 형식의 10진수로 변수에 저장된다
  • 1byte만 읽는다.
  • 한글을 제대로 인식하지 못한다.

*cf) 자세한 utf-8 입력 - utf-16 메모리 -utf-8 출력에 대해 알고 싶다면, Reference 참고하자. 설명이 잘 되어 있다.

*cf)컴퓨터는 모든 데이터를 바이트 단위 데이터로 구성되어 있다. 즉 데이터를 저장하던, 전달하던 컴퓨터에는 바이트 단위로 데이터가 저장된다.

3. Scanner(System.in) , InpuStreamReader(System.in)

Scanner (System.in) -> 자바 기본적인 입력스트림 inputStream을 활용하여 하고 ,매개변수 (System.in) 을 사용하여 InputStreamReader 라는 객체를 만드는 것을 알 수 있다.


InputStreamReader 의 특징 (문자 스트림)

  • InputSteam의 바이트 단위로 읽어 들이는 형식을 문자단위 (character) 로 데이터로 변환시키는 중개자 역할을 한다고 생각하면 좋다.
  • char 배열로 데이터를 받을 수 있다.

*cf) 바이트 데이터를 문자단위로 변환하는 것은 charSet 이라는 class가 담당한다. 이 덕분에, utf-8 의 한글이 3byte 여도 2byte로 변환해주기 때문에, 자바 메모리가 2byte를 쓰는 utf-16이여도 대입이 가능한 것이다.

Scanner 의 작동과정을 순서대로 작성해보면

1. InputStream 을 통해 (바이트 스트림)을 입력받음
2. byte to char (InputStreamReader 역할)
3. 입력받는 문자는 입력 메소드의 종류에 따라 정규식 검사
4. 정규식 문자열을 Pattern 타입으로 변환 ( 내부 임시배열로 문자들 ->문자열 처리)
5. 변환된 Pattern -> String 변환
6. String은 입력메소드에 맞게 타입으로 변환
ex) nextInt -> Integer.parseInt() 이런식으로

4. BufferedReader

BufferedReader br = new BufferedReader(new InputStreamReader(System.in))

//자세하게 풀어쓰면
InputStream inputstream = System.in;
InputStreamReader sr = new InputStreamReader(inputstream);
BufferedReader br = new BufferedReader(sr);

BufferedReader의 존재 이유

InputStreamReader byte to char type 으로 처리하는 것은 해결되었다.
but 입력받은 싶은 것이 문자열이라면, 처리하기 굉장히 불편하다.
이것들을 해결하기 위해 나온것이 BufferedReader 이다.

BufferedReader는 Buffer를 통해 입력받은 문자를 쌓아둔 뒤 한번에 문자열 처럼 보낸다.

요약
Byte Type = InputStream
Char Type = InputStreamReader
Char Type 의 직렬화 = BufferedReader

BufferedReader의 특징

  • 버퍼가 있는 스트림이다.
  • 별다른 정규식을 검사하지 않는다. -> 성능이 Scanner보다 좋은이유이다.

BufferedReader 작동원리 한줄 요약:
즉, 정리하자면 바이트 단위 [InputStream]로 문자를 입력받아 문자(character) [InputStreamReader]로 처리한 뒤 버퍼(buffer) [BufferedReader]에 담아두었다가 일정 조건이 되면 버퍼를 비우면서 데이터를 보내는 것이다.

전체 내용 사진으로 한장 정리!

작성일 : 2022년 05월 12일

reference

https://st-lab.tistory.com/41

추가공부 필요한 Keywords

: UTF-8, Modified UTF-8, UTF-16 , UNICODE, 인코딩, 디코딩

profile
개발자 지망생입니다.

0개의 댓글