ANSI에 대해

http://ko.wikipedia.org/wiki/EUC-KR

위의 링크 내용을 요약하면
CP949 = 현대 한글 + EUC-KR
EUC_KR = KS X 1001 + KS X 1003
KS X 1001 = 한글 및 한자 모음
KS X 1003 = ASCII + '\(원 문자)'
정도 되겠음다.

유니코드에 대해

http://b.mytears.org/2005/01/101

Unicode는 기본적으로 Byte order mark 후에 해당하는 글자들이 나오게됩니다.
즉 UTF-8의 경우( 아래 표 참조 )
EF BB BF EA B0 80 EA B0 80
이렇게 적혀 있으면
가가
라고 보이게 됩니다.
단, UTF-8에 한해서 Byte order mark가 없어도 상관없습니다.

Encoding UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE
‘가’ EA B0 80 AC 00 00 AC 00 00 AC 00 00 AC 00 00
Smallest code point 0000 0000 0000 0000 0000
Largest code point 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF
Code unit size 8 bits 16 bits 16 bits 32 bits 32 bits
Byte order N/A big-endian little-endian big-endian little-endian
Byte order mark EF BB BF FE FF FF FE 00 00 FE FF FF FE 00 00
Minimal bytes 1 2 2 4 4
Maximal bytes 6 4 4 4 4

위에 Code unit size에도 나와있듯
Unicode는 무조건 2바이트 혹은 4바이트인 것은 아닙니다.
1바이트가 아닌 문자는 Wide Character라고 하죠.

즉, Unicode는 C++에서 Wide Character를 나타내는 wchar_t와는 그 개념이 아주 다릅니다.
wchar_t는 char처럼 단순히 일정한 크기[각주:1]일 뿐이고
이것으로 표현되는 것은 UCS-2 혹은 UCS-4와 같은 고정바이트 형 문자인 것이죠.
따라서 최소 단위가 1 Byte인 UTF-8은 char로 취급해야만 합니다.
그렇지 않으면 제대로 처리되지 않아요.[각주:2]

ANSI와 UTF-8의 상호 변환

리눅스에서는 iconv라는 함수를 제공합니다.
man iconv_open
을 치면 상세한 설명이 나와있습니다. ( 남자는 man. 그 후 스타죠. )
콘솔창에서는
iconv -f UTF-8 -t CP949 -o cp949.txt utf-8.txt
이런 식으로 쓰면 됩니다.
다만 UTF-8에서 다른 포맷으로 변경시 Byte order mark를 인식하지 못합니다.
즉, 파일의 처음이 EF BB BF로 시작하면 iconv로는 다른 포맷으로 변경이 되지 않습니다.
안타깝지만 파일의 처음을 열어서 Byte order mark가 있으면 제거해주는 루틴이 필요합니다.
파일 인코딩 포맷을 알 수 있는 명령어로는
file <file>
이 있습니다. 이를 이용하면
utf8.txt: UTF-8 Unicode text, with no line terminators
와 같이 떠요.
UTF-8의 Byte order mark를 인식 못하는 것은 iconv뿐이고 나머지에서는 잘 인식됩니다.

윈도우에서는 MultiByteToWideChar()를 제공합니다.
유사 포맷으로는 mbstowcs()가 있지만 이 함수는 UTF-8은 제공하지 않습니다.
ANSI 코드에서 UTF-8로 가기 위해서는 다음과 같은 변환과정을 거쳐야 합니다.
ANSI( MutiByte ) -> UCS-2( WideByte ) -> UTF-8( MultiByte )
대략 코드로 보면 다음과 같습니다.
void foo( const char *in, char *out, int nOut )
{
    USES_CONVERSION;
    wchar_t *wc = A2W( in ); // ANSI to UCS-2
    WideCharToMultiByte( CP_UTF8, 0, wc, -1, out, nOut, 0, 0 ); // UCS-2 to UTF-8
}
참고로 A2W나 USES_CONVERSION은 ATL 관련 함수입니다.
반대로 변환할 떄는 MultiByteToWideChar()W2A()를 이용하시면 됩니다.
위에도 적어놨지만 ANSI나 UTF-8이나 다 MultiByte입니다.
A2W()는 내부적으로 MultiByteToWideChar()를,
W2A()는 내부적으로 WideCharToMultiByte()를 호출합니다.
매크로를 쓴 건 예제 길이를 짧게 하고 싶어서 쓴 거니 너무 신경쓰진 마세요.

이거 찾는다고 Managed Extension까지 갔다오고
벼라별 짓을 다 했는데..
결국 저 3줄이면 충분하더군요.
나름 쓸모있을 내용같아서 정리해서 포스팅합니다.

참고

유니코드에 관한 설명
http://b.mytears.org/2005/01/101

EUC-KR, CP949 에 관한 위키피데아
http://ko.wikipedia.org/wiki/EUC-KR

API를 이용하는 유니코드와 ANSI 문자열간의 변환 방법
http://www.winapiprogramming.com/MyHome/api.htm#2 (링크 깨짐)

  1. Windows API에서는 2 Bytes, Linux에서는 4 Bytes [본문으로]
  2. stania군 제보로 수정, stania 감사! [본문으로]

댓글을 달아 주세요

  1. BlogIcon bassist. 2007.03.22 19:47  address  modify / delete  reply

    베리즈 프로젝트에서 저 작업을 하는 CodeConverter가 있습니다. 꽤 마음에 들어서 사용하고 있는데 한 번 참고해 보시는 것도 좋을 것 같아요.

  2. stania 2007.05.03 19:13  address  modify / delete  reply

    wchar_t 가 언제나 short 인건 아닌걸로 알고 있어용. wide character 의 한 글자를 처리하기 위한 단위인데 Windows 환경에선 UTF-16을 다루기 위한 용도로 한정되다보니 ushort 와 같은 크기(내지는 typedef)로 처리되는거지요.
    wchar_t 는 개발 환경(혹은 컴파일러)에 따라 달라질 수 있어요. VS 등에서는 프로젝트 옵션에서 wchar_t 를 어떻게 다룰지 정할 수 있기도 하고 뭐 그렇죠. wikipedia wchar_t 를 살짝 보시면 좋을듯!

  3. 2012.01.25 02:22  address  modify / delete  reply

    비밀댓글입니다

    • BlogIcon 디지츠 2012.01.26 19:12 신고  address  modify / delete

      아니요.. 이 포스팅은 단순히 C++ 프로그래밍만을 위한 것으로 일반적인 문서를 다룰 때엔 굳이 저 순서로 할 필요가 없어요. 메모장에서 단순히 다른 이름으로 저장 후에 Encoding을 바꿔주는 것만으로도 충분히 될 거 같은데요.. 안 된다면 E-Mail로 보내서 다시 받는 등의 방법 혹은 HTML Editor에 올려다 다시 가져오는 방법 등을 한번 써 보세요.

  4. ? 2013.05.06 02:34  address  modify / delete  reply

    그래 이거지