지난 포스팅에서
스트림(Stream)에 대해서
알아보았다.
스트림(Stream)은 프로그램 안팎으로
들어오거나 나가는 바이트 흐름을 의미한다.
바이트 스트림 vs 문자 스트림
기본적으로
스트림에는 두 가지 종류가 있다.
1. 바이트 스트림 2. 문자 스트림
'바이트 스트림'은 데이터를 1byte 단위로 읽는다.
반면에 '문자 스트림'은 2byte 단위로 읽는다.
파일은 OS에 영향을 받는다.
그러므로 OS인코딩 방식을 따른다
윈도우는 MS949 인코딩 방식으로 파일을 저장한다.
JVM이 돌아가면서 RAM에는 문자열이 UTF-16으로 저장된다.
Java는 String 객체 내부(메모리 상에서) UTF-16 BE 인코딩으로 문자열을 저장하고, 문자열을 입/출력할 때에만 사용자가 지정한 인코딩 값 또는 운영체제의 기본 인코딩 값으로 문자열을 인코딩한다. JVM 기본 인코딩은 JVM 로딩 시에만 초기화되므로, 코드 중간에서 file.encoding 프로퍼티를 바꾸는 것은 아무 의미가 없다. 만약 file.encoding이 지정되어 있지 않다면, OS 환경 변수(예: LANG) 값을 따른다.
문자 - 이진수 - 십진수
String과 char는 출력만 되면되고
int형은 연산이 가능해야 한다.
그러므로 int는 이진수를 십진수로 변환한것이된다.
0~127 까지는 어떤 인코딩 방식도 모두 동일하다.
int = > String으로 바꾸면 숫자가 안 바뀜
1byte를 읽은 후 이를(문자로 인식) int로 바꾸면 문자에 대응되는 아스키 코드 십진수가 출력
바이트 스트림
바이트 스트림은 1byte 단위로 읽어들인다.
바이트 스트림의 읽기를 담당하는 InputStream 클래스를 확인해보자. 스트림을 읽는 read 메소드는 크게 두 가지가 있다.
1. read()
2. read(byte[] b)
read() 메소드는 스트림에서 1byte 데이터만 읽어온다. 그리고 int 형으로 return한다.
데이터를 byte[] 배열 안에 저장 가능하다.
실제로 InputStream 클래스의 read 메소드를 보면, 매개변수로 받은 바이트 배열(byte[])에 해당 바이트 배열에 스트림으로 전달 받은 데이터를 저장한다. 그렇게 되면, 바이트 배열을 통해 스트림으로 전달 받은 데이터를 사용할 수 있다.
문자 스트림의 경우, 2byte 단위로 전달받으므로 char 배열(char[])을 사용한다. (Java에서 char형은 2byte를 차지한다.)
Reader 클래스의 read 메소드를 보면, 매개변수로 받은 char 배열(char[]) 스트림으로 받은 데이터를 저장한다. 그렇게 되면, 우리는 char[] 배열을 통해, 스트림으로 전달받은 데이터를 사용할 수 있다.
이렇듯, 1byte 단위로 읽어들인 데이터는 byte[] 배열 혹은 byte 변수에 저장가능하고 2byte 단위로 읽어들인 데이터는 char[] 배열 혹은 char 변수에 저장 가능하다.
채팅프로그램을 만든다고 가정해보자. 채팅을 오로지 영어로만 한다면 바이트 스트림 방식으로 데이터를 읽는 것이 용이하다. 반면에 채팅을 한글로 할거라면 문자 스트림 방식으로 데이터를 읽어야 한다.
이렇듯 문자 스트림은 오로지 유니코드 상의 문자를 위한 방식이다. 그러므로 이미지나 동영상 파일의 경우, 바이트 스트림 방식을 사용해야 한다. 1byte 단위로 데이터가 구성된 이미지 파일을 2byte 단위로 읽어들이면 이미지는 깨지게 된다. 그러므로 반드시 바이트 스트림 방식을 사용해야 한다.
만약 유니코드 문자를 바이트 스트림 방식으로 읽어들였다면 반드시 인코딩을 해주어야 한다. 유니코드 문자는 2byte(16bit) 단위로 문자를 나타내기 때문에 1byte로 읽어들인 바이트열(array)을 프로그램 안에서 인코딩 해준 후, 문자 데이터를 사용해야 문자 데이터가 깨지지 않는다. 인코딩 관련해서는 나중에 자세히 다루어 보겠다.
InputStream, OutputStream vs Reader, Writer
JAVA에서 바이트 스트림 방식과 문자 스트림 방식을 사용하려면 관련된 API가 있어야한다. 표준으로 제공되는 API는 바이트 스트림 방식에는 InputStream 클래스와 OutputStream 클래스가 있고 문자 스트림 방식에는 Reader 클래스와 Writer 클래스가 있다.
바이트 스트림 방식과 문자 스트림 방식은 바이트 열(array)을 읽느냐 문자 열(array)을 읽느냐의 차이가 있지만 사실상 매커니즘은 같다. InputStream 객체와 Reader 객체는 read()를 하고 OutputStream 객체와 Writer 객체는 write()하고 flush() 한다.
추상클래스
InputStream과 OutputStream
그리고
Reader와 Writer
이 4 가지 클래스는 '추상 클래스(Abstract Class)'이다.
추상 클래스란 여러 클래스의 공통적인 특성만 추려 생성한 클래스이다. 그러므로 InputStream, OutputStream, Reader, Writer는 바이트 스트림과 문자 스트림의 역할과 기능에 대한 추상적 개념만 제시할 뿐 실제 사용되는 객체는 따로 있다.
이와 같이, InputStream과 Reader 기능을 갖춘 여러가지 클래스들이 존재한다. 이들은 사용되는 방식에 따라 기반 스트림과 보조 스트림으로 나뉜다. 이 내용은 다음 포스팅에서 다루어 보겠다.
https://d2.naver.com/helloworld/76650
'JAVA > JAVA Basic' 카테고리의 다른 글
[ JAVA ] JVM이 문자열을 UTF-16 방식으로 저장하는 이유 (3) | 2021.07.06 |
---|---|
[ JAVA ] 문자 인코딩(Character Encoding)이란? (0) | 2021.07.05 |
[ JAVA ] 제네릭 (Generic) 심화 ( 와일드 카드 + 상속 ) (0) | 2021.06.20 |
[ JAVA ] 제네릭 (Generic) (0) | 2021.06.20 |
[ JAVA ] 스레드(Thread) 동기화5 (Implicit Lock vs Explicit Lock ) (0) | 2021.06.20 |