UTF-8, UNICODE, ANSI - 인코딩에 대하여

2012. 12. 13. 16:2899. 정리전 - IT/29. IT 잡동지식

출처 : http://blog.naver.com/declspec?Redirect=Log&logNo=10092640244


영어 이외의 문자를 표현하기 위하여 ANSI 인코딩이 사용되는데

이는 2바이트 문자와 1바이트 ascii 문자를 혼용하는 가변길이 인코딩이고

이 인코딩으로 한글이 무난하게 전부 표현되지만 더 많은 문자들을 인코딩하지는

못한다.  예로 ANSI 인코딩에서의 한글인코딩을 보면 B0 A1 으로 '가' 가 시작하지만

B0 A2 를 보게되면 '각' 이 되고 B0 A3 의 경우 '간' 으로 인코딩된다

 

하지만 유니코드 인코딩의 경우 ANSI 의 각 과 간 사이에 더많은 문자가 들어간다

갂, 갃 이 그사이에 들어가는 것이다.

 

이는 ANSI 인코딩이 아무래도 실제로 사용하는 한글만 대상으로 인코딩한것에 비하여

유니코드는 가능한 모든조합을 만든것 같다.

 

유니코드는 사실상 HTTP 프로토콜등에서 거의 사용하지 않는데

UTF8 이나 ANSI 보다 별로 사용되지 않는 이유는 ASCII 와의 호환이 안되기때문이다.

 

유니코드에서 한글 '가' 의 인코딩값은 AC 00 이며 일반 ASCII 문자또한 모두 16비트로

인코딩되며 확장된 비트가 0으로 채워지기때문에 모든 ASCII 문자에는 ASCII 로 해석할경우

null 문자가 들어가게되며 멀티바이트 문자들도 예외는 아니다.

 

하지만 ANSI 인코딩만으로는 그렇게 많은 문자들을 인코딩할수 없기때문에

나온것이 UTF8 로 추정된다.

 

UTF8 은 가변길이 인코딩인데 1바이트에서 5바이트까지 폭넓게 변할수 있으며

몇바이트로 인코딩 되는가는 해당 문자의 유니코드값의 범위에 좌우된다.

 

예를들어 한글의경우 유니코드 0800 ~ FFFF 의 범위에 모두 들어가는데

이는 UTF-8 에서 3바이트로 인코딩된다.

 

 

구글링을 해보면 UTF-8 과 유니코드간의 변환규칙을 쉽게 찾을수있다.

그러나 UTF-8 과 ANSI 와의 변환규칙은 아무리 찾아도 나오지 않았다.

 

일단 UTF8 - UNICODE 변환규칙은 한글만 따지면 다음과 같다

UTF8 의 첫번째 바이트의 하위 4비트.

두번째 바이트의 하위 6비트

마지막 바이트의 하위 6비트

 

이 비트들을 concat 하면 16비트 유니코드가 되는것이다.

 

 

그렇다면 UNICODE 와 ANSI 를 변환할수있다면

UTF8 과 ANSI 도 변환할수 있지 않을까?

 

싶어서 규칙을 구글링하니 역시 없다.

 

그래서 그냥 유니코드 한글표를 이용해서 ANSI 로 변환하는

방법을 이용하기로했다.

 

유니코드가 다행히 순차적으로 1씩 증가하며 모든한글을 포함하기때문에

유니코드값을 가지고 그에 대응되는 ANSI 인코딩 문자열이 있는 표가 있으면

변환이 가능한데 인터넷에서 쉽게 찾았다.

 

아무튼 이러하 점들을 이용하여 UTF8 - UNICODE - ANSI 변환 함수를

C로 다음과 같이 만들었는데 g_ftable 은 유니코드 한글이 ANSI 인코딩으로

순서대로 기록되어있는 파일포인터이다.

 

아무튼 잘 동작한다

 

이제 UTF8 을 ANSI 로 변환하여 쉽게 콘솔에 나타낼수있다

사실 이것을 만든이유는 리눅스 콘솔상에서 UTF-8 을 보려고 한것인데

ioconv 인지 뭔지 하는 프로그램이 있지만 사용법도 매우 귀찮아보이고

그냥 나만의 함수를 만들고 싶었다.

 

// UTF8 -> UNICODE -> ANSI 변환 (1110xxxx 10xxxxxx 10xxxxxx)
void PrintUTF8(unsigned char a, unsigned char b, unsigned char c){

 int unicode; // UTF8 문자의 유니코드대응값

 int p, q, r;

 p = a % 16;  // 상위 4비트 추출
 q = b % 64;  // 중간 6비트 추출
 r = c % 64;  // 하위 6비트 추출

 unicode = p;
 unicode = unicode << 12;  // 4비트를 12비트 L 쉬프트
 unicode = unicode | (q << 6); // q를 6비트 L 쉬프트한것을 비트OR 시킴
 unicode = unicode | r;   // 하위 6비트를 비트OR 시킴
 
 // 44032 부터의 차를 구함 ( 0xAC00 : '가' )
 int offset = unicode - 44032;

 // ANSI 한글 인코딩이 2바이트이므로 offset*2
 offset = offset * 2;

 // ANSI - UNICODE 테이블에서 해당 오프셋으로 이동
 fseek(g_ftable, offset, SEEK_SET);

 
 char ansi[3]; // 2바이트 + NULL
 
 ansi[2]=0;
 fread(ansi, 1, 2, g_ftable); // table 에서 ANSI 인코딩문자를 읽어들임

 // ANSI 인코딩으로 출력
 printf("%s", ansi);


}