[JAVA] I/O Char 와 Encoding

2019. 8. 7. 11:31 JAVA/Java IO

I/O Char 와 Encoding


데이터는 다양한 종류가 있다. 이미지, 오디오, 비디오, 바이너리 파일 등이 있지만 가장 많이 사용하는 것은 문자이다.

따라서 문자의 형태를 직접 읽고 쓰기 위한 클래스가 제공되는데 이때 인코딩(Encoding)이 사용된다.


1. ASCII 코드와 한글


자바는 영미권에서 만들어져서 영어로 입출력할 때는 문제가 없지만 제 3의 언어로 입출력을 실행하면 문제가 발생하는 경우가 많다. 이것은 각 문자의 인코딩과 관련 문제이다.


(1) ASCII 코드


영어를 사용할 때는 알파벳 소문자 대문자 52개의 문자와 10진수 숫자 10개가 필요하다. 그리고 쉼표, 따옴표, 물음표 등등의 문장 부호들이 60개 정도가 지정되어 있다.

따라서 영어를 사용하기 위해서는 120개 정도의 개수가 필요하다.


컴퓨터로 이 모든 것을 표현하기 위해서는 7비트면 충분하다. (2의 7승 = 128)

이 7비트의 문자 체계가 ASCII 코드이다.


하지만 유럽에서는 영문 알파벳 외에 추가적인 글자들이 있다. 그래서 8비트로 하나의 비트를 더하고 이 비트를 구분자로 유럽에서 사용하는 문자를 추가하여 표현하는 것을 Latin-1 이라고 한다.


이와 같이 128 ~ 255의 빈 공간을 사용하는 것을 Extended ASCII 이라고 하고 한글 역시 이 공간을 사용해야 한다.


(2) 한글의 표현


한글은 초성, 중성, 종성이 합쳐져 하나의 문자가 된다. 한글은 15 비트가 있어야 하나의 한글을 표현할 수 있다.


한글은 1바이트로는 표현할 수 없어 2바이트를 겹쳐서 한 글자를 표현하는 방법을 사용한다. (Multi Byte Character Set)

이러한 방법으로 표현된 인코딩(Encoding)을 "EUC-KR" 이라고 하며, 윈도 OS에서는 MS949 라는 코드로 부르기도 한다.


각 나라의 문자별로 자신들의 Extended ASCII 을 사용하여, 표준 인코딩이 필요하게 되었다.



(3) 표준화 문제


"EUC-KR" 인코딩을 사용하지 않는 다른 나라에서 한글 데이터를 받으면 아마 이상한 문자로 깨져서 나올 것이다. 반대로 다른 나라의 고유 문자를 데이터로 받으면 우리나라에서 이상한 문자로 깨져서 나올 것이다.

동일한 바이트 데이터라도 인코딩 방식에 따라 다른 문자로 인식된다.


따라서 다양한 문자를 서로 해석할 수 있도록 인코딩의 표준화가 필요해졌다.



2. 유니코드(Unicode)와 UTF


(1) 유니코드(Unicode)


ISO 에서는 표준화하기 위한 코드는 적어도 2바이트가 되어야 한다는 결론을 내리고 세계의 모든 글자를 2바이트로 표준화하여 표현하는 유니코드(Unicode)를 표준으로 채택하였다.


유니코드(Unicode) 채택의 가장 중요한 포인트는 전 세계 26개 언어가 모두 포함되어 있다는 것과, 어떤 나라에서도 같은 데이터를 공유할 수 있다는 것이다.


자바는 유니코드를 지원할 수 있도록 내부적으로 사용하는 글자의 크기를 2바이트로 지정하였다.


유니코드를 사용하여 표현하는 한글과 아스키를 이용하여 표현하는 한글은 똑같은 글자를 표현한다고 하더라도 바이트 데이터는 서로 다르다.

실제로 "가"에 해당하는 ASCII 데이터는 0xB0A1 으로 표현되지만 유니코드에서는 0xAC00으로 표현된다. 따라서 같은 한글이라 할지라도 어떤 인코딩을 적용했는가에 따라 전혀 다르게 해석되고 조합될 수 있다.


(2) UTF-8


유니코드를 사용하여 표준화를 진행한 것은 매우 좋지만 영미권에 속한 나라는 오히려 불편해졌다. ASCII를 기준으로 1바이트로 하나의 문자가 되었지만 유니코드를 사용하면서 한 문자에 2바이트가 사용되어 데이터 공간이 2배 이상 필요하게 되었다. 그래서 UTF-8이 나왔다.


UTF-8은 가변 길이를 지원하는데 각 언어별로 최적화된 크기로 저장할 수 있도록 1바이트에서 3바이트까지 표현이 달라진다. 영문 같은 경우는 1바이트로 표현되고 한글의 경우는 3바이트의 데이터로 표현된다. 따라서 같은 한글이라도 사용하는 인코딩에 따라 바이트 크기가 달라진다.



3. JAVA와 인코딩


자바에서는 바이트 데이터를 기준으로 문자를 만들어 낼 때 인코딩이 적용된다.


char 와 String 클래스에 인코딩이 적용되며 입출력과 관련되어 ByteStream에서 Char Stream으로 변환되는 클래스에도 적용된다.


String 클래스의 생성자를 보면 바이트 배열을 어떤 인코딩으로 해석하여 문자를 생성할 것인지 지정하는 생성자가 있다.

반대로 기존의 String 객체를 어떤 인코딩을 통하여 바이트 배열로 분해할 것인지를 지정해서 실행하는 getBytes()라는 메소드도 존재한다.


만약 자바에서 글자가 깨진다면 깨진 글자를 getBytes()로 분해했다가 새롭게 String 객체를 만들어 출력하면 해결된다.



출처: https://hyeonstorage.tistory.com/251?category=578560 [개발이 하고 싶어요]