달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

Windows 환경에서 C/C++을 사용하여 코딩할 때 utf-8과 cp949의 인코딩을 변환하는 방법은 크게 두 가지가 있습니다. 첫째로는 Windows에서 제공해주는 MultiByteToWideChar()와 WideCharToMultiByte()라는 API를 이용하는 것이고, 둘째로는 리눅스나 php를 써 보신 분이라면 익숙한 iconv를 사용하는 것입니다. iconv를 사용하는 것이 직관적으로 볼 때에는 상당히 편하므로 이 방법을 쓰는 것도 좋지만, 애석하게도 iconv는 MinGW 출시 이후로 Visual Studio에서의 포팅에 관한 지원을 끊었습니다. 다행스럽게도 Visual Studio에 대한 지원이 끊긴 지 얼마 안 되었고, 헤더 파일도 몇 개만 바꿔 주면 될 정도로 상당히 간단한 작업을 통해 dll로 포팅할 수 있습니다. 자세한 사항은 링크를 참조해주세요.
[win32] iconv 포팅하기
또, (wx)Dev-C++이나 mingw를 사용하시는 분들에 한해서 iconv를 별다른 복잡한 과정 없이 쉽게 쓰실 수 있습니다. 이에 관해서는 전에 포스팅한 링크를 남겨드리니 이 링크를 참조하시기 바랍니다.
iconv() - 문자열 인코딩 변환

하지만 Windows 환경에서 제공되는 다른 컴파일러의 경우는 얘기가 다릅니다. iconv를 쓸 수 없다면 인코딩표를 참조해서 직접 코딩을 하거나, 인터넷에서 돌아다니는 사용법도 모르는 소스를 일단 프로젝트에 추가해야 하죠. 만약 추가한 소스에서 에러가 난다면 생판 처음 보는 남의 코드를 디버깅해야 하는 웃지 못할 일이 벌어지기도 합니다. 그래서 전 Borland C++ 등의, Windows에서 돌아가는 다른 컴파일러에서도 쉽게 쓸 수 있도록 API를 활용하는 방안을 여러분들께 말씀드리고자 합니다.


사실 WinAPI에서는 cp949 - utf8을 바로 바꿔 주는 함수는 존재하지 않습니다. 대신에 cp949 - Unicode(UTF16), Unicode - UTF8을 지원해주지요. 우리는 Unicode를 중간 매개로 삼아 cp949 - utf8 변환을 할 것입니다.

먼저 cp949 - Unicode를 살펴보겠습니다. cp949에서 Unicode로 변환하는 것은 MultiByteToWideChar()란 함수를 통해 할 수 있습니다. MSDN에서 발췌한 내용에 따르면 원형은 이렇게 된다는군요.

int MultiByteToWideChar(   __in   UINT CodePage,   __in   DWORD dwFlags,   __in   LPCSTR lpMultiByteStr,   __in   int cbMultiByte,   __out  LPWSTR lpWideCharStr,   __in   int cchWideChar );


cp949에서 Unicode로 변환하기 위해서는 다음과 같이 함수를 사용하면 됩니다.

char ansi[MAX]; // 여기 안에 원문이 있다고 가정합시다. ^^* 
WCHAR unicode[MAX]; // 여기엔 변환할 문자열을 넣을 것입니다. 
 
// 혹시 모르니까 깔끔하게 정리해주고... 
memset(unicode, 0, sizeof(unicode)); 
 
// 변환! 
MultiByteToWideChar(CP_ACP, 0, ansi, -1, unicode, sizeof(unicode));


CodePage는 multibyte 원문의 인코딩 형식을 나타내는 건데요, ANSI이므로 CP_ACP를 써줍니다. 여러 가지가 많지만 하나하나 설명해드리진 않겠습니다. 자세한 건 아래의 MSDN 링크를 참조해주세요.
lpMultiByteStr는 원문의 포인터 주소를 나타내는 것입니다. 쓰기 작업이 되지 않으니 const char *를 써 주셔도 됩니다. 
cbMultiByte는 최대로 변환할 바이트 수인데, 일반적으로 strlen()을 활용해서 넣기도 합니다만 굳이 그걸 쓰지 않아도 됩니다. -1은 "Null 문자까지 포함해서 문자열 전체"라는 뜻이니까요.
lpWideCharStr는 유니코드로 변환할 데이터가 저장될 공간을 나타내는 것이고, cchWideChar는 버퍼의 크기를 나타냅니다. 일반적으로 sizeof를 써 줍니다.

이제 Unicode - utf8을 보겠습니다. 이번에는 WideCharToMultiByte()란 함수를 쓸 건데요, 이 함수는 매개 변수 두 개가 추가된 것 외엔 별다른 게 없습니다. 원형을 봅시다.

int WideCharToMultiByte(   __in   UINT CodePage,   __in   DWORD dwFlags,   __in   LPCWSTR lpWideCharStr,   __in   int cchWideChar,   __out  LPSTR lpMultiByteStr,   __in   int cbMultiByte,   __in   LPCSTR lpDefaultChar,   __out  LPBOOL lpUsedDefaultChar );


Unicode에서 utf8로 변환하려면 다음과 같이 코드를 써 주면 됩니다.

WCHAR unicode[MAX]; // 위에서 변환한 정보가 그대로 있다고 생각합시다^^ 
char utf8[MAX]; // 여기에 변환할 문자열을 넣겠습니다. 
 
// 정리 정리 
memset(utf8, 0, sizeof(utf8)); 
 
// 변환! 
WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf8, sizeof(utf8), NULL, NULL);


UTF8로 변환할 것이므로 CodePage에 CP_UTF8이 오신 걸 보실 수 있습니다.
뒤에 두 개의 매개 변수가 추가되었는데, 실제로 사용한 부분을 보시면 둘 다 NULL로 채워버린 걸 보실 수 있습니다. 이런 식의 변환에는 그다지 중요하지 않으므로 자세한 설명은 생략하겠습니다. 확실히 알고 싶다면 마찬가지로 MSDN 링크를 참조해주세요.

이제 반대로 UTF8에서 cp949로 가 봅시다. 위의 예제를 꼼꼼히 보셨다면 별다른 생각 없이 쉽게 구현하실 수 있습니다. 먼저 UTF8에서 Unicode로 변환해보겠습니다.

char utf8[MAX]; // utf8로 인코딩된 문자열이 이미 들어가 있다고 생각합시다. 
WCHAR unicode[MAX]; // 유니코드 버퍼 
 
memset(unicode, 0, sizeof(unicode)); 
 
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, unicode, sizeof(unicode));



바로 Unicode에서 cp949로 변환해보겠습니다.

WCHAR unicode[MAX]; 
char ansi[MAX]; 
 
memset(ansi, 0, sizeof(ansi)); 
 
WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, sizeof(ansi), NULL, NULL);


이렇게 코딩하시면 됩니다.


위에서 썼던 방법을 쓰기 좋게 통합하면 다음과 같습니다.
ANSI to UTF8

string ansi_to_utf8(string& ansi) 
{ 
    WCHAR unicode[1500]; 
    char utf8[1500]; 
 
    memset(unicode, 0, sizeof(unicode)); 
    memset(utf8, 0, sizeof(utf8)); 
 
    ::MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, unicode, sizeof(unicode)); 
    ::WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf8, sizeof(utf8), NULL, NULL); 
 
    return string(utf8); 
}


UTF8 to ANSI

string utf8_to_ansi(string &utf8) 
{ 
    WCHAR unicode[1500]; 
    char ansi[1500]; 
 
    memset(unicode, 0, sizeof(unicode)); 
    memset(ansi, 0, sizeof(ansi)); 
 
    ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, unicode, sizeof(unicode)); 
    ::WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, sizeof(ansi), NULL, NULL); 
 
    return string(ansi); 
}



C++에서 쓰이는 string이 조금 들어갔는데, 이 정도는 C에서 사용할 수 있도록 쉽게 바꿀 수 있으므로 C 언어에서 쓰는 방법을 따로 소개해드리진 않겠습니다.

 

추가;; C에서 사용할 수 있게 변경

char* utf8_to_ansi(char *utf8) 

    WCHAR *unicode = NULL; 
    char *ansi = NULL; 
 
 unicode = (WCHAR*)calloc(1, strlen(utf8)*2);
    ::MultiByteToWideChar(CP_UTF8, 0, utf8, -1, unicode, strlen(utf8)*2);

 ansi = (char*)calloc(1, _tcslen(unicode)*2);
    ::WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, _tcslen(unicode)*2, NULL, NULL); 
 
    return ansi; 
}



링크:
MSDN - WideCharToMultiByte
MSDN - MultiByteToWideChar

 

 

출처:http://marnitto.edogawa.kr/71


출처:http://blog.naver.com/PostView.nhn?blogId=nimi315&logNo=50093464158


Posted by dewlit
|