유니코드 .. 멀티바이트 이놈들 -ㅅ-..

꼭 필요하긴하지만 ..막상쓰면 뷁쒧뗅뙓 같은 녀석들이다 -_ㅠ..

 

친절하게도

MultiByteToWideChar()

WideCharToMultiByte()

라는 함수를 제공해주지만..

 

굉장히 사용이 복잡하다는 문제점을 안고 있다.....

(크기설정 이나 옵션설정도 필요하다 -_-)

 

그래서 찾다 발견한 ...

 

#include <atlconv.h>
 USES_CONVERSION; // W2A , A2W를 사용하기 위한 디파인..

W2A() // 유니코드->멀티

A2W() // 멀티 -> 유니코드

 

 

사용하기전에

 USES_CONVERSION;

해줘야하는 점이 좀 복잡하긴하지만..

뭐 그래도 훨씬 간단한 것이다!!!!!!

 

 char szMult[] = "멀티녀석들!!";
 wchar_t szWide[] = L"유니코드닷";


 USES_CONVERSION;
 strcpy(szMult, W2A(szWide)); // 유니코드 -> 멀티바이트 복사
 _tcscpy(szWide, A2W(szMult)); // 멀티바이트 -> 유니코드 복사

 

뭐 그래도 훨씬 간단한 것이다!!!!!!

'C/C++언어 > 유니코드' 카테고리의 다른 글

CSting의 유니코드를 파일로 저장 & 로드 할때  (1) 2007.11.18
유니코드 정보 모음  (0) 2007.11.18
유니코드의 사용법  (0) 2007.09.06

일단 이것땜에 숙제, 턴프로젝트, 할일등 모두 내 팽겨쳐 졌다.. orz

유니코드는 이 아래에서 긁어온 자료와 같이 여러 종류가 있다고 한다.

하지만 지금 중요한건 저 글자를 파일로 저장한뒤 온전하게 불러오는데 목적이 있다.

예제는 한줄경우 어떻게 처리가 되었지만, 몇백줄 넘어가는 자료를 저장하면 그 나름대로 테크닉이
필요하다.

데브 피아 등 여러곳을 돌아다니가 결국 잘못된곳을 찾아냈다..

다음은 J-Notebook 프로그램의 파일 저장 소스 일부분이다.

if(dlg.DoModal() == IDOK)
 {
  CFile file;
  CFileException e;
  if(!file.Open(dlg.GetFileName(), CFile::modeWrite | CFile::modeCreate, &e))
  {
   e.ReportError();
   return;
  }
  // 파일을 쓴다. 음... file.Write가 \n 이 자동으로 붙고, \r\n하면 한줄씩 내려준다.
  // 유니코드 시작
  WORD  a;
  a = 0xFEFF;
                                   <- 16진수 변환 프로그램을 보니, 제대로 읽히는 파일은 FFFE로 시작한다.
                                       하지만 FEFF로 넣었다.. 왜냐? 윈도우는 리틀 앤디안이기 떄문이라;;;
  file.Write((void*)&a, sizeof(a));
                                // 맨 처음부분에 넣어준다. 왜인지 모르겠지만 아무래도 유니코드 식별인자 인거 같다;;

  // 유니코드에서 한줄내림은 코드는 0x0a인듯 하다..
  a = 0x0A;
  JWord note;
  CString strWord;
 
  int i=0;
  for(; i < pDoc->m_szNoteWord.size()-1; i++)
  {
   note = pDoc->m_szNoteWord[i];
   strWord.Format(L"%s;%s;%s;%d\r",note.word, note.yomigana, note.mean, note.count);
   // 글자를 쓰고,
   file.Write(strWord, strWord.GetLength()* sizeof(wchar_t));
   // 이 글자의  유니코드식별자? 를 추가해준다.. 파일흐름상 개행라인인거 같다.
   file.Write((void*)&a, sizeof(a));

  }
  // 마지막은 개행할 필요가 없으므로 따로 써준다.
  note = pDoc->m_szNoteWord[i];
  strWord.Format(L"%s;%s;%s;%d",note.word, note.yomigana, note.mean, note.count);
  file.Write(strWord, strWord.GetLength()* sizeof(wchar_t));
 }

이짓을 해주면. CFile::typeText | CFile::modeRead 로 문제없이 읽어온다.

하지만... 유니코드... 이거 난해해서.. 괜한 지뢰밭 들어간건 아닌지 걱정된다.

유니코드 정보 모음 | 기타 기술정보
전체공개 0 / 2007.05.20 12:04


UTF의 개념
UTF는 16bit 유니코드 문자들을 7비트 또는 8비트 문자로 변환하기 위한 방법이다.
UTF-8은 유니코드를 8비트 문자로 변경하는 것입니다.
유니코드란 - 각각의 다른 나라를 시스템의 호환성 및 확장성에 문제를 일으키는 관계로
이를 하나의 문자인 유니코드로 통합시켜 표현하는 방법중에 한가지입니다.


UTF-8의 동작 방법
DNS를 찾을 경우 클라이언트에서 utf-8로 인코딩 되어 서버의 ip주소를 찾아 갑니다.
그러나 특정한 사이트인 경우 utf-8을 지원하지 못할 수 도 있고 서버에 접속을 못할 수 도 있습니다.

유니코드 용어의 이해

유니코드 관련 문서를 읽다보면 가장 많이 마주치는 용어들이
UCS2, UCS4, UTF8, UTF16, UTF32 등과 같은 단어들입니다.

기본언어판, BMP (Basic Mulitilingual Plane)
유니코드의 첫 65,536개의 코드를 의미합니다.

언어판, Plane (256x256 즉 65,536 개씩의 코드 묶음)
유니코드에서는 현재 17개의 언어판을 사용할 수 있습니다.
모두 그룹 00에 포함됩니다.

언어판 그룹, Group (256개씩의 언어판을 묶어 하나의 그룹)
유니코드의 17개 언어판은 모두 Group 00에 있습니다.
유니코드는 17개의 언어판에 한정되어 정의됩니다.
반면 ISO 표준(UCS-4)에서는 모두 128개의 언어판 그룹이 정의될 수 있습니다.
1 Plane = 65,536 code points
1 Group = 256 planes = 256x65,536 = 16,777,216 code points
UCS-4 = 128 groups = 128x16,777,216 = 2,147,483,648 code points

인코딩, Encoding (문자집합을 표현하는 방식)
유니코드는 코드체계 또는 문자집합을 명명하는 것이며 이를 표현하기 위해서는
UTF-8, UTF-16, UTF-32 등과 같은 인코딩이 필요합니다.

UCS-2: Universal Character Set 2(octets)
좀더 정확하게는 Universal Multipe-Octet Coded Character Set 2입니다.
ISO/IEC 10646의 용어로 BMP의 65,536 코드를 정의하며, 2바이트로 표현됩니다.
1개의 언어판, 즉 BMP만이 이에 해당합니다.
UCS-2는 인코딩 방법이 아니며 문자코드 자체입니다.
인코딩으로 봐도 무방하겠군요. 여기서 octet이라는 용어를 사용했는데 이 용어는
ISO쪽에서 사용하는 용어로, 유니코드 진영에서 사용하는 바이트와 같은 뜻입니다

UCS-4: Universal Character Set 4(octets)
ISO/IEC 10646의 용어로 4바이트로 표현됩니다.
모두 128개의 언어판 그룹, 즉 128*256 언어판 = 32,768 언어판을 정의합니다.
이는 대략 231 = 2,147,483,648개의 코드에 해당합니다.
UCS-4는 인코딩 방법이 아니며 문자코드 자체입니다.

UTF-8: UCS Transformation Format, 8-bit form
Unicode 표준의 인코딩 방식중의 하나입니다.
표준에서는 17개 언어판의 문자만을 표현할 수 있으나 기술적으로는
UCS-4 전영역의 문자를 표현할 수 있습니다.
문자에 따라 1 ~ 4(또는 6) 바이트로 표현됩니다.

UTF-16: UCS Transformation Format, 16-bit form
유니코드 3.0에서는 16을 16비트로 해석한 것이 아니라,
그룹 00의 16개 언어판이라고 써 놓았군요.
UTF-32의 32가 32비트를 지칭하므로 통일성을 위해 16비트로 이해하시는 게 좋습니다.
16비트로 표현한다는 점에서는 UCS-2와 흡사하지만 대행문자영역(Surrogates)을
이용하여 16개의 보충 언어판 코드를 표현할 수 있는 인코딩입니다.
대행문자영역 2개로 16개의 보충 언어판을 표현할 수 있습니다.
UCS-2에서는 65536개의 코드만을 정의할 수 있으나 UTF-16에서는
1백만여자를 더 표현할 수 있습니다.

UTF-32: UCS Transformation Format, 32-bit form
32비트 즉 4바이트로 각 문자를 표현합니다.
이점에서 UCS-4와 동일하지만 17개의 언어판만을 정의한다는 점에서는
UCS-4의 부분집합으로 간주하면 됩니다. UCS-4와 동일하나
0x00000000 ~ 0x0010FFFF 범위만을 문자코드로 간주한다고 이해하시면 됩니다.

출처 : http://cafe.naver.com/crazysystem/189


-------------------------------------------------------------------------


데브피아 VC QA 게시판에서 발췌.


1) "한글abc"가 유니코드로 써있다면 한글과 영어 구분은 어떻게 해요


    --> 영어와 한글은 code range가 다른 영역에 위치하므로 영역검사로 충분히 구분가능합니다.


2) 유니코드빌드로 하지 않고도 유니코드를 노트패드처럼 유니코드 txt문서로 저장할 수 있나요? 그런 함수는 없는것 같아요.


    --> 가능합니다. 저장할 data를 mbstowcs, MultiByteToWideChar를 통해 멀티바이트 데이타에서 unicode 데이타로 저장합니다.


3) 유니코드빌드로 해도 유니코드 txt문서로 저장할수없다고 앞에서 본거같은데 사실인가요?

    --> 유니코드는 크게 2가지로 보면 됩니다. (사실은 더많지만)

                UCS2 : 이것은 정말로 모든 문자로 2바이트로 표현되서 프로그램 내부의 데이타표현형으로 씁니다.

                            (WCHAR가 이경우죠)


                UTF8 : 이것은 영문은 1바이트 그외의 문자는 2~6(?)바이트의 가변바이트로 저장하게 됩니다.

                            영문권얘들이 자기네 기존 영문데이타와 호환시키기위해 만들었는데 파일저장등에 사용합니다.


            그러므로 저장시에 위의 포맷중 어느것인 확인해서 저장해야겠지요.    UTF8저장경우에는 내부의 WCHAR를

                다시 UTF8 encoding으로 변환해서 저장해야합니다.

                       

4) 유니코드로 해도 데이타베이스에 저장하려면 또 그 데이타베이스가 쓰는 유니코드로 바꿔야한다는데 사실인가요?


        아마 위의 UCS2와 UTF8등의 선택이 있겠지요.. 그러나 ODBC등을 사용한다면 encoding변환에 문제가 없지 않을까요?


5) 유니코드로 해도 윈도우 OS에 쓰는 유니코드와 맞게 고쳐야 유니코드 txt로 저장할수 있는건가요?

        UCS2라 하더라도 OS에 따라 bigendian format으로 little endian format으로 저장하는 것에 차이가 좀있습니다.


6) 유니코드도 종류가 많아서 오히려 쓰기 불편할거 같은생각도 드는데 괜한걱정인가요?

        어차피 encoding 변환 함수를 사용한다면 유니코드encoding변환끼리는 큰 문제가 되지 않을 겁니다.

        encoding변환함수를 짜는 사람이 머리아픈것이지...


        제가 보기에는 파일로 저장형식으로는 UTF8을 일반적으로 많이 쓰이는 것 같습니다.



----------------------------

이정신

http://redhotfrog.mytripod.co.kr




----------------------------------------------------------------------------------------------



아래 데브피아에서 QnA 발췌

자주올라오는 질문들에 대한 응답을 한번 모아보았습니다.

 보충하고 싶은 내용은 메일을 요청바랍니다.


/////////////////////////////////////////////////////////////////////////////

UNICODE PRIVATE FAQ 0.1 (2004.08.03) by redfrog@jitco.net


----------------------------------------------------------------------------

A000 : character set, code set, encoding, codepage가 뭡니까?

A001 : MBCS, SBCS, DBCS가 뭡니까?

A002 : i18n, l10n이 뭡니까?

A003 : 유니코드가 뭡니까?

A004 : 유니코드 UCS2에서 UTF8로 변환은 어떻게 하나요?

A005 : windows 9x와 windows NT계열 OS의 차이.

A006 : C/C++의 표준 문자열정의.

A007 : MFC의 TCHAR.

A008 : "한글abc"가 유니코드로 써있다면 한글과 영어 구분은 어떻게 해요.

A009 : 중국어는 유니코드에서 어떻게 다루나요?

A010 : 유니코드와 파일

A011 : db에 저장하려면 또 그 dbms가 쓰는 유니코드로 바꿔야한다는데 사실인가요?

A012 : database에서는 어떻게 다루나요?

A013 : 참조할 만한 자료들.

----------------------------------------------------------------------------


이것을 저는 UTF8로, 즉 8비트로 변환을 하고자 하는데 어떻게 하면 될까요?


============================================================================

A000 : character set, code set, character encoding, codepage가 뭡니까?

----------------------------------------------------------------------------

character set이란 문자의 집합입니다. 단 이때 각문자에는 숫자코드가 부여됩니다.

그렇지만 코드숫자가 컴퓨터상에서 어떻게 표현되는 가는 정해지지 않은 상태라고

보면 됩니다.


encoding이란 character set에 좀더 제약이 강해서 컴퓨터상에서 어떻게 표현 되는가까지를

정해진 상태의 문자의 집합입니다. 같은 그림이라도 압축방법에 따라 gif, png,

bmp등등의 파일형식이 있듯이 code set과 encoding의 차이를 이해할 수도 있을

겁니다. 실제 예를 들면 완성형한글인 KSC5601 codeset은 UNIX에서는 euc-kr이란

encoding으로 표현되고 DOS에서는 codeset 949란 encoding으로 표현됩니다.


오래전에는 character set과 character encoding은 같은 말이었습니다.

그러나 언젠가 부터 시스템의 종류도 많아지고 다국어시스템의 지원등등 여러여건들에

의해 character set에서 부터 character encoding이 분리된 것이죠.


code set이란 말은 어쩔 때는 character set의 의미로 어쩔 때는 encoding의

의미로 사용됩니다. 그렇다 보니 문맥을 보고서 적당히 해석해서 사용을 해야 합니다.


codepage는 IBM에서 사용하던(?) 말로 encoding과 같은 것으로 보면됩니다.

MICROSOFT에서 DOS를 만들때 IBM과 같이 만들었기 때문에 MICROSOFT에서는

codepage라는 말을 많이 사용합니다.


============================================================================

A001 : MBCS, SBCS, DBCS가 뭡니까?

----------------------------------------------------------------------------

MBCS이란 Multibyte code Set으로 하나의 문자를 표현하는 code가 문자에 따라

한 바이트로도 여러 개의 바이트로도 표현되는 encoding을 의미합니다.

완성형 한글의 경우 영문은 1바이트로 한글/한자는 두 바이트로 표현됩니다.


SBCS란 Singlebyte code Set으로 하나의 문자를 표현하는 code가 항상 한 바이트로

표현될 수 있는 encoding을 의미합니다.


DBCS는 Double Byte code Set으로 하나의 문자를 표현하는 code가 한 바이트나

두 바이트인 encoding을 의미합니다.


windows환경에서는 SBCS와 DBCS가 MBCS의 특수한 경우로 처리됩니다.



============================================================================

A002 : l10n, i18n이 뭡니까?

----------------------------------------------------------------------------

l10n은 localization(지역화)의 약칭입니다. 개발자들이 긴 낱말이 싫어서 약어로

사용하는 말입니다. 소프트웨어가 localization되어있다는 말은 소프트웨어를

사용하는 사용자를 위해 한 언어에 맞추어 개발이 되어있다는 겁니다. 그래서

이 경우에는 한번에 다중언어를 사용할 수 없습니다.


i18n은 internationalization(국제화)의 약칭입니다. software가

internationalization되었다는 말을 들을려면 여러언어를 예를 들면 한국어든

중국어든 동시에 입력해서 사용할 수 있어야 합니다.


multiligual system이란 말과 i18n system은 동일한 말입니다.



============================================================================

A003 : 유니코드가 뭡니까?

----------------------------------------------------------------------------

영문권에서 i18n을 위해서 만든 character set입니다.

유니코드가 나오기 이전에는 i18n system을 만들기가 어려웠습니다. 왜냐하면

여러언어를 포함하는 하나의 단일 character set이 없었기 때문입니다. 그래서

예전에는 여러 character set을 포함하는 가상의 character set을 각 소프트웨어회사마다

내부적으로 만들어서 사용하였습니다. 그러다보니 호환이 잘 안되겠지요.

그래서 유니코드 콘소시엄을 결성하여 모두가 동의하는 문자셋을 만들게 되었습니다.

이것이 바로 유니코드입니다. 유니코드에서 정의하는 character set은 UCS2와

UCS4가 있습니다. 우리가 보통 일반 프로그램을 개발할 때는 UCS2를 기반으로

만들게 됩니다. UCS4는 산스크리트어나 옛 이집트 고어와 같은 것까지 포함하는

것으로 알고 있습니다. 그러므로 보통 유니코드라고 말할 때는 UCS2를 지칭합니다.


UCS2/UCS4는 character set이면서 encoding으로도 존재합니다. 이 encoding의

특징은 UCS2경우에는 영문을 포함한 모든 문자가 두 바이트로 표현되고 UCS4경우에는

네 바이트로 표현됩니다. 이렇게 고정된 길이의 encoding을 쓰면 장점은

문자열내의 특정 문자를 index로 쉽게 접근할 수 있다는 것입니다. MBCS처럼

문자마다 길이가 다른 경우에는 n번째 문자를 접근하려면 문자열의 처음부터

검색을 해야 한다는 점을 생각한다면 문자열처리에 잇점이 있겠지요.


그러나 UCS2 encoding에 장점만 있는 것은 아닙니다. 문제는 기존의 ASCII기반으로

된 모든 소프트웨어와 데이타베이스를 UCS2로 업그레이드해야만 UCS2와 호환된다는

겁니다. Y2K보다 더 황당한 비용이 발생하겠지요. 그래서 이러한 단점을

보완하기 위한 encoding이 UTF7, UTF8입니다. 이 encoding들의 특징은 기존 MBCS처럼

한문자가 1바이트에서 여러바이트를 가질 수 있습니다. 이 경우 encoding의 디자인이

기존 ascii파일은 utf8 encoding을 하더라도 차이가 없도록 되어 있습니다. 즉 ascii파일은

그냥 utf8 encoding이 되어있다고 가정해도 상관없는 겁니다.


그래서 실제적으로 프로그램이 유니코드를 지원한다고 하면 내부적으로는 UCS2/UCS4 encoding을

사용하고 파일/데이타베이스 같은 외부자원에 대해서는 UTF7/UTF8과 같은 encoding을

사용합니다. 즉 혼용해서 사용하는 겁니다.


============================================================================

A004 : 유니코드 UCS2에서 UTF8로 변환은 어떻게 하나요?

----------------------------------------------------------------------------


WINDOWS API에서 보면 WideCharToMultiByte라는 함수가 있습니다.

이 함수의 인터페이스는 다음과 같습니다.


    int WideCharToMultiByte(

      UINT CodePage,            // code page

      DWORD dwFlags,            // performance and mapping flags

      LPCWSTR lpWideCharStr,    // wide-character string

      int cchWideChar,          // number of chars in string

      LPSTR lpMultiByteStr,     // buffer for new string

      int cbMultiByte,          // size of buffer

      LPCSTR lpDefaultChar,     // default for unmappable chars

      LPBOOL lpUsedDefaultChar  // set when default char used

    );


이 함수의 첫번째 매개변수 CodePage에 CP_UTF8를 할당하여 사용합니다.



============================================================================

A005 : windows 9x와 windows NT계열 OS의 차이.

============================================================================


windows 9x (windows 95,98,me)계열은 windows api를 표준적으로 ANSI 버젼을 지원합니다.

즉 unicode를 windows api에서 직접지원하지 않고 mbcs만을 직접지원합니다.

이 때 ANSI는 MBCS라고 생각해도 무방합니다.



windows NT (windows NT, windows 2000, windows XP등등)계열은 windows api를

ANSI버젼과 UNICODE버젼을 모두 지원합니다. ANSI버젼의 API를 쓰는 경우에는

OS가 api를 다시 UNICODE버젼으로 변환합니다. 그러므로 UNICODE로 버젼으로

만들어진 프로그램은 windows NT계열에서 약간의 속도향상을 가져올 수 있습니다.

그러나 windows 9x에서 동작하지 않는 단점이 있습니다. 그래서 microsoft에서는

windows 9x계열에서 UNICODE버젼으로 개발된 소프트웨어를 손쉽게 동작하게 하기

위해서 windows 9x용 unicode를 지원 dll을 제공합니다. 컴파일시 이 dll을 이용하면

unicode버젼으로 개발되었어도 windows 9x계열에서 동작가능합니다.



============================================================================

A006 : C/C++의 표준 문자열정의.

============================================================================


"안녕"이라고 literal을 표현하면 이것은 MBCS(언어규격 표준 용어로는 mcs)입니다.

L"안녕"이라고 literal을 표현하면 이것은 UCS encoding (언어규격 표준 용어로는 wcs)입니다.

어떤 encoding을 따르는 것인가는 compiler와 OS에 따라 다릅니다.

예를 등어 windows에서 visual studio 6.0 한글버젼을 사용하는 경우 MBCS로 컴파일시

codepage 949를 따르게 됩니다.


char데이타표현은 MBCS의 문자를 표현하는데 사용합니다. char는 사실 1바이트로

고정되어 있으므로 MBCS의 문자는 한 char또는 두 char로 표현됩니다.


wchar_t데이타표현은 UCS의 문자를 표현하는데 사용합니다. 많은 경우 2바이트이지만

시스템에 따라 4바이트거나 8바이트일 수도 있습니다. 이러한 UCS문자를

언어규격 표준 용어에서는 wide character라고 합니다.



============================================================================

A007 : MFC의 TCHAR.

============================================================================

MFC는 소스를 수정할 필요없이 mbcs 와 unicode 간의 compile switch을 손쉽게해주는

많은 macro를 제공합니다. strcpy같은 형태가 아니라 _tcscpy와 같은 방식으로 말이죠..

또한 strcpy를 와 같이 mbcs에서 먹는 함수를 바로 써버리면 아무리 UNICODE switch로

compile해보아보았자 MBCS로 컴파일되게 됩니다. 되도록이면 TCHAR계열 마크로를

쓰는 습관을 들이는 것이 중요합니다.


MBCS모드에서는 TCHAR는 char로 그리고 _tcscpy는 strcpy로 변환됩니다. _T("문자열") ---> "문자열"


UNICODE모드에서는 TCHAR가 wchar_t로 그리고 _tcscpy는 wcscpy로 변환됩니다. _T("문자열") ---> L"문자열"


============================================================================

A008 : "한글abc"가 유니코드로 써있다면 한글과 영어 구분은 어떻게 해요

============================================================================


영어와 한글은 code range가 다른 영역에 위치하므로 영역검사로 충분히 구분가능합니다.

자세한 것은 www.unicode.org에 있는 문자 테이블을 참조하십시요..


참고로 MBCS로 컴파일된 경우 완성형을 쓰기 때문에 영문검사시 if (ch < 0x80)

해도 무리가 없습니다.




============================================================================

A009 : 중국어는 유니코드에서 어떻게 다루나요?

============================================================================

중국어는 크게 두가지가 있습니다. 간체 (simplified)와 번체(traditional)이

그 것입니다. character set자체가 다르지요.


번체는 대만에서 표준으로 정립한 문제체계로 예전부터 내려온 기존한문을

그대로 씁니다. 그래서 이름이 traditional이라고 불리우는 것이지요..


간체는 중국본토에서 표준으로 정립한 문제체계로 공산화되면서 많은 한문문자가

약자로 표기되기 때문에 그내용도 약자한문을 담고 있습니다.

그래서 이름이 simplified이라고 불리우는 것이지요.


GB라고 앞에 붙은 encoding이나 character set은 간체를 의미합니다. GB-2312가

처음에 나와서 GBK의 서브셋으로 보면되고 보통은 이정도만 구현해도 많이 작동을

하지만, windows의 지원하는 중국어 간체는 GBK(GB-18030)이라고 보시면 됩니다. 몇

글자는 약간 변경되었지만요. 그리고 나온 것이 GB2K로 알고 있습니다. Unicode는 GB-

18030과 호환이라 보시면될 겁니다. 그외는 저도 기억이 잘나지 않네요.


홍콩이나 싱카폴등등에서 만든 문자셋도 있지만 요즘은 거의 쓰이지 않고 점차

간체가 힘을 쓰는 것 같습니다. 국력에 비례하네요..


============================================================================

A010 : 유니코드와 파일

============================================================================

유니코드 switch로 compile을 처음 해보는 경우 마추치게 되는 문제의 하나가

왜 파일에 저장시 유니코드로 저장되지 않는가 하는 점이다. 앞에서

말했듯이 유니코드라고 하더라도 다양한 encoding이 있으며 유니코드 switch는

API 함수와 자료들을 위한 ucs2 encoding만을 지원한다는 점이다. 즉 파일에

저장한다던지 utf encoding등으로의 변환등은 여전히 전적으로 개발자의 몫으로

남는다는 점이다.


파일로 저장시에는 많은 경우에는 UTF8 encoding을 사용하게되는데 이때는

WideCharToMultiByte API를 사용해서 변환하면 된다.


UTF계열이 아니라 UCS를 바로 저장하는 경우에는 조심해야 하는 것이

byte order이다. 이것은 CPU에 따라 다르게 되어있는데 intel계열은 little

endian이라 는 불리우는 바이트 순서로, 그 외 mac이나 workstation계열은

많은 경우 big endian으로 불리우는 바이트 순서를 가진다. 그러므로

CPU와 OS에  따라 bigendian format으로 little endian format으로 저장하는 것에

차이가 있다.


============================================================================

A011 : db에 저장하려면 또 그 dbms가 쓰는 유니코드로 바꿔야한다는데 사실인가요?

============================================================================

아마 UCS2와 UTF8등의 선택이 있겠지요.. 그러나 ODBC등을 사용한다면

encoding변환에 문제가 없지 않을까요?


============================================================================

A012 : database에서는 어떻게 다루나요?

============================================================================

어떤 분이 database에 대해 문의를 하셨는데 저도 줏어 들은 것 밖에 없고

실제 경험이 없기 때문에 확실한 답변은 안되어도 전에 응답하였던 내용을

올려 봅니다.



질문 :

    UTF8로 세팅된 DB에서 일본어문자를 ODBC를 통해 VC++어플리케이션에서

    가져옵니다.(rsData.GetFieldValue) 그런데 이 UTF8문자가 어플리케이션에서

    가져오면서 유니코드로 저절로 바뀌어서 들어옵니다. [(예)DB에 저장된

    문자열("????"  (12바이트)를 어플리케이션에서 CString으로 가져와서

    GetLength()한값은 8바이트로 찍힙니다.)] 이걸 UTF8로 유지시키려면 어떻게

    해야하나요? (일본어문자하나가 3바이트로 인식되게) 또 전체 어플리케이션의

    코드셋을 UTF8로 바꾸려면 어떻게 해야하나요?


응답 :

    ------------------------------------------------------------------------

    UTF8로 세팅된 DB에서 일본어문자를 ODBC를 통해 VC++어플리케이션에서

    가져옵니다.(rsData.GetFieldValue) 그런데 이 UTF8문자가 어플리케이션에서

    가져오면서 유니코드로 저절로 바뀌어서 들어옵니다.

    ------------------------------------------------------------------------


        ODBC가 UCS2로 자동변환하는 것 같습니다.


    ------------------------------------------------------------------------

    이걸 UTF8로 유지시키려면 어떻게 해야하나요? (일본어문자하나가 3바이트로

    인식되게)

    ------------------------------------------------------------------------

        그럴 필요가 정있다면 다시 UCS2를 UTF8문자열로 바꾸는 WideCharToMultiByte

        함수를 사용하세요. 단 이때 대상 인코딩을 CP_UTF8로 지정하십시요..



    ------------------------------------------------------------------------

    또 전체 어플리케이션의 코드셋을 UTF8로 바꾸려면 어떻게 해야하나요?

    ------------------------------------------------------------------------

        한글과 같은 Multibyte set과 UCS2만을 지원하신다고 보시면 됩니다.

        이론적으로는 UTF8를 기준으로 프로그램을 만들 수는 있지만 의미는 없습니다.

        MFC나 모든 관련 API들이 유니코드지원할 때 UCS2 기준으로 만들어져 있기 때문입니다.

        그러므로 필요할 때만 UTF8로 변환하여 사용하십시요.

       

       


질문 :

    우선 저희 솔루션은 한국어용으로 개발된것인데요 이번에 프로젝트에서 중국어와

    연계가 된 부분이 있어서 일부분을 수정작업하고 있습니다 중국어 문자열을

    추출하여 오라클에 저장하는 프로그램입니다. 그런데 별짓을 다해도

    ???????????????????? 이런식으로 깨져버리는군요 디비는 UTF-8부터해서 한국어

    확장완성형까지 다 바꿔봤지만 결국은 디비 문제가 아닌것을 알았습니다. 디비에

    입력할때 중국어가 깨지는것 같은데?


응답 :

    db의 encoding이 UTF8로 일단 맞춘것으로 가정하죠.


    ????????????????????으로 깨졌다는 것은 데이타가 UTF8형식으로 되어 있지

    않다는 것을 의미합니다. 즉 application이 db에 데이타를 넣을 때 utf8형식으로

    입력을 하지 않았다는 것이죠..


    제가 보기에는 application이 한글지원으로 만들어졌을 때 unicode가 아닌

    multibyte형식으로 compile되어 있는 것같습니다.


    다국어버젼 특히 단일 프로그램으로 다국어를 지원하는 경우에는 unicode형식을

    지원하도록 application을 수정하여야 합니다.


============================================================================

A013 : 참조할 만한 자료들.

============================================================================

1. MSDN

    당연히 윈도우즈에서 개발하려면 MSDN이 없으면 안되겠지요..

   

2. www.unicode.org

    유니코드 콘소시엄 공식 사이트입니다.

   

3. UTF계열 encoding

    자세한 정보가 http://www.elfdata.com/plugin/storage.html 에 잘 나와있네요..

   

4. 전문가가 되려면 다음 책은 필수 입니다.

    그러나 이것은 전문가를 위한 책입니다. 먼저 기본 지식을 습득한 후에 보세요.

   

    Title       : CJKV Information Processing (Chinese, Japanese, Korean &

                    Vietnamese Computing)

    Author      : Ken Lunde

    Publisher   : O'Reilly Media, Inc.

    ISBN        : 1-56592-224-7





-------------------------------------------------------------------------


아래 unnicows dll 링크관련 정보


Here is what MS says:

1. Add the following two files to your project:
   UnicoWS.dll -- the Microsoft Layer for Unicode DLL
   UnicoWS.lib -- the LIB file to which you link

Note that the Microsoft Layer for Unicode does not automatically load from
the $(WINDOWS) or $(WINSYS) directories. Thus, do not put UnicoWS.dll there
unless you are running from a system process that is located there. Instead,
keep the UnicoWS.dll in your application directory and call LoadLibrary
yourself to ensure that you load the correct .dll.

*** I did it: now unicows.dll is in my application directory
*** I receive no more the "unicows.dll not found" error but...
*** ... now I have an error on Kernel32.DLL  :(

Add the following to the link options for your application (note that these
libraries are not separated by commas because that is how you add them to
the link list):
First, add the following:
/nod:kernel32.lib /nod:advapi32.lib /nod:user32.lib /nod:gdi32.lib
/nod:shell32.lib
/nod:comdlg32.lib /nod:version.lib /nod:mpr.lib /nod:rasapi32.lib
/nod:winmm.lib
/nod:winspool.lib /nod:vfw32.lib /nod:secur32.lib /nod:oleacc.lib
/nod:oledlg.lib
/nod:sensapi.lib.

*** Not done: which are already added by wxWidget? Which are not? Help
required!

2. Then add UnicoWS.lib.

Finally, add the libraries that the Microsoft Layer for Unicode uses
explicitly:

kernel32.lib advapi32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib
version.lib mpr.lib rasapi32.lib winmm.lib winspool.lib vfw32.lib
secur32.lib
oleacc.lib oledlg.lib sensapi.lib.

In this step, omit any libraries listed after kernel32.lib whose APIs are
not used in your application. However, if your application uses another
component, such as MFC, ATL, or CRT, be sure to include any libraries on
which the component depends.

*** Same as before. What sould I add and what should I not?

3. Compile your application.

If you are using side-by-side assemblies, you must define
MICROSOFT_LAYER_FOR_UNICODE as 1.

*** I assume this is done by wxWidget when I set MSLU to 1.

When you follow these steps, the Microsoft Layer for Unicode loads itself by
calling LoadLibrary. However, if you want to control the loading of the
UnicoWS.lib you must perform the following additional steps. (These steps
are also necessary if you are using side-by-side assemblies.)

*** Is this the case of wxWidget?

To control loading MSLU or use side-by-side assemblies
Add the following code to your application:
#ifdef _cplusplus
extern "C" {
#endif
extern FARPROC _PfnLoadUnicows = (FARPROC) &LoadUnicowsProc;
#ifdef _cplusplus
}
#endif

*** I assume this is done by wxWidget? Is it?

Define the LoadUnicowsProc function. This function is a user-defined
callback function that takes no parameters. The loader calls it when needed
to load the Microsoft Layer for Unicode. Note that LoadUnicowsProc is only
called on Windows 95/98/Me. Also, LoadUnicowsProc is called before the
DllMain PROCESS_ATTACH call and, for an .exe, before WinMain.

*** I assume this is done by wxWidget? Is it?

HMODULE LoadUnicowsProc(void);
The following is a typical implementation of LoadUnicowsProc.
HMODULE LoadUnicowsProc(void)
{
    return(LoadLibraryA("unicows.dll"));
}

Note that you must call LoadLibraryA and all other Ansi APIs explicitly.
This is because compiling as Unicode defines APIs like LoadLibrary as
LoadLibraryW. For more information, see Conventions for Function Prototypes.

*** I assume this is done by wxWidget? Is it?

If you load the Unicows.lib in this manner, you must never call any of the
APIs that the Microsoft Layer for Unicode itself wraps. Doing so leads to a
stack overflow because your callback calls the loader which calls your
callback, and so forth.

*** ????

Thank you for any help... in advance ;-)

DdJ


출처 카페 > 게임 개발자 네트워크 (jz.. / 자존심
원본 http://cafe.naver.com/jzsdn/2284

♧ 유니코드


-싱글바이트와 더블바이트

: strlen을 호출하면 싱글바이트 문자들의 문자열 종결자(제로)배열내 문자들의 수를 리턴한다. 문제는 몇 언어들과 쓰이고 있는 시스템들 (예 : 일본어 kanji)이 싱글바이트가 제공하는 최대 256개의 심볼보다 더 많은 기술을 사용한다는 것이다. 그래서 더블바이트 문자세트는 이런 언어들과 기록시스템을 지원한다. (비주얼 C++런타임 라이브러리 : _mbslen함수)


- 1988년 애플과 제록스 사에 의해 표준화


- 더블바이트 문자세트는 다음 바이트가 같은 문자의 일부인지 새로운 문자인지 구분해야 하는데 유니코드는 그럴 필요가 없어서 CharNext, CharPrev와 같은 함수는 필요가 없다. 또한 16비트 값으로 표현하기 때문에 65000이상의 문자들을 이용할수 있으므로 싱글바이트 문자세트로 256문자들을 이용하는것과는 많은 차이가 난다.


- 현재 29000코드 포인트들이 할당되지 않고 있어서 이것들은 미래의 사용을 위하여 보류된 것이다. (키릴어, 영어, 히브리어, 아라비아어 등등을 표현한다)


- 유티코드를 사용하는 이유

        ? 언어들 사이에서 쉬운 데이터로 변환이 가능

        ? 모든 언어를 지원하는 싱글 바이너리, .exe  또는 DLL파일의 분배가 가능

        ? 애플리케이션의 효율향상


- 윈도우 2000은 유니코드 사용을 근거로 만들어졌다. 즉, 윈도우 함수를 호출하고 그것을 ANSI문자열로 넘기면, 시스템은 처음에 그 문자열을 유니코드로 바꾸고, 그 다음 유니코드 문자열을 운영체제로 넘긴다. 또한 함수로부터 ANSI문자열을 기다린다면, 애플리케이션으로 돌아가기 전에 시스템은 유니코드 문자열을 ANSI문자열로 변환한다. 물론 이런 변환을 수행하기 위해서는 시간과 메모리의 오버헤드가 존재한다.

예를들어, CreateWindowEx를 호출하고 유니코드가 아닌 클래스 이름과 윈도우 캡션을 전달하게 되면, CreateWindowEx는 메모리 블록을 할당해야 하고, 유니코드가 아닌 문자열을 유니코드로 바꿔야 한다. 그리고 그 결과를 할당된 메모리 블록에 저장하고, 유니코드버전 CreateWindowEx를 호출하는 함수를 만들어야 한다. 또한 문자열을 버퍼에 넣는 함수에서는 애플리케이션이 그 문자열을 처리히기 전에 시스템은 반드시 유니코드를 유니코드가 아닌 코드로 바꾸어야 한다. 그러므로 처음부터 유니코드를 사용하는 애플리케이션을 개발함으로써 능률적으로 수행하게 할 수 있다.


- Microsoft Unicode Story

        ? 윈도우 2000은 유니코드와 ANSI를 지원한다. 즉 둘 중 하나로 개발할 수 있다.

        ? 윈도우 98은 ANSI만 지원하므로 ANSI로만 개발해야 한다.

        ? 윈도우 CE는 유니코드만 지원하므로 유니코드로만 개발해야 한다.


- COM : 문자열을 요구하는 모든 COM인터페이스 메소드는 단지 유니코드 문자열만 받도록 되어있다. 왜냐하면 COM은 전형적으로 다른 컴포넌트가 서로 대화할 때 사용되고, 유니코드는 문자열을 전달하는 좋은 방법이기 때문이다. 만일 윈도우 98로 개발하고 COM을 사용한다면 많은 문제가 발생할 것이다.


- 유니코드 소스 작성하는 방법

? typedef unsigned short wchar_t;

wchar_t szBuffer[100]; 이렇게 버퍼를 생성한다. 물론 strcpy, strcat같은 표준 c런타임 문자열함수는 ASNI문자열만 연산한다. 그래서 그에 대응하는 유니코드함수가 있다.

char* strcat(char*, const char*);

wchar_t* wcscat(schar_t*, const wchar_t*);

이렇게 모든 유니코드 함수는 wcs(wide character string)로 시작한다. 그러므로 str을 wcs로 변경하면 된다.


- CreateWindowExW와 CreateWindowExA함수 프로토타입 비교

? PCWSTR : 상수 유니코드 문자열 포인터

? 윈도우 2000에서 CreateWindowExA의 마이크로소프트 소스코드는 단순히 청크(thunking)또는 변환, 즉 ANSI문자열을 유니코드 문자열로 바꾸기 위한 레이어가 된다.

그래서 코드는 바꾼 문자열을 전달하여 CreateWindowExW를 호출한다.


- ANSI와 유니코드를 대비한 애플리케이션 만들기

? 윈도우 문자열 함수 : lstrcat, lstrcmp, lstrcmpi, lstrcpy, lstrlen

: 이들 함수는 소스 모듈이 컴파일될 때 UNICODE가 정의되었는지에 따라 유니코드 버전 함수나 ANSI버전 함수를 호출하는 매크로로 구현된다. 즉, lstrcat는 lstrcatA와 lstrcatW로 확장될 것이다.

? 일반적인 데이터타입(TCHAR과 PTSTR과 같은)을 텍스트문자와 문자열로 사용한다.



- 유니코드는 한마디로 말하면 모든 문자를 2byte로 표현하자는 의미이다.

- 98은 전혀 지원하지 않는다.

- CE은 유니코드만 지원한다.

- 2000은 유니코드와 ANSI를 지원한다.

- 미래 os는 유니코드만 지원하게 될 거 같다.

- 그래서 코드를 재 사용할 때 문자열 표현에 문제가 생긴다.

예)char sz[100] : 미래에는 char보다 short int로 컴파일 해야한다.

그래서 지금 코딩할 때 유니코드 버전을 대비해서 미리 코딩하는 기법을 써야한다.

- 유니코드 쓰는 방법 : short int sz[100];

그런데 아직은 전부 다 이렇게 쓸 수가 없다.

- 유니코드를 쓰는 세 가지 관점

① 변수 선언

② 상수 선언

③ 함수 선언


1) 변수 선언


- char나 short int를 쓸 수 없어서 매크로를 만들어 놨다. : TCHAR

이러면 상황에 따라서 두 가지로 컴파일이 된다. 유니코드는 short int로, ansi는 char로 컴파일이 된다. 그러므로 앞으로는 TCHAR을 쓰는 게 좋다.

윈도우 CE에서 작업할 때 기존의 소스를 포팅하려면 char를 전부 수정해줘야 하는 문제가 생긴다.

- 포인터 변수일 경우는 (정수는 문제가 되지 않기 때문에 char *를 말한다) TCHAR*로 써줘야 한다.  그래서 이것도 다음과 같이 매크로로 만들어 놓았다.

- LPCTSTR : 상수형이다. c가 있으면  TCHAR* 상수형이다

- LPTSTR : TCHAR* 버퍼형이다. 즉 배열을 잡아서 써야한다. 그렇지만 LPCTSTR은 상수형이므로 바로 "HOWON"과 같이 쓸 수 있다.

-LPCSTR, LPSTR : 이것들은 T가 없으므로 여전히 char*로만 컴파일이 된다. 그래서 쓰지 않는다.


2) 상수 선언


- 문자열 상수 "   "를 말한다. "abc"면 \0까지 포함해서 4byte인데 이걸 유니코드에서

컴파일하면 여전히 4바이트이다. 그래서 유니코드 상수로 하여 L"abc"로 하면 8바이트가 된다. 그러나 이렇게 하면 지금 당장 컴파일이 안되므로 역시 매크로를 만들어 왔다.

- _T, TEXT : _T("abc") 이렇게 쓰면 컴파일될 때 현재 상황은 "abc"가 되고 유니코드로 컴파일하면 L"abc"가 된다.

TEXT는 API용이고 _T는 MFC용이다.


3. 함수사용


- strcpy는 char*를 인자로 받는다. 그래서 유니코드에서는 이 함수를 쓰지 못한다.

그래서 유니코드용 문자열 복사 함수를 만들어 놓았다. wcscpy(short int*  )

그런데 지금 코딩할 때는 이걸 쓸 수 없으므로 역시 매크로를 만들어 놓았다. : _tcscpy

이 함수는 지금 컴파일 하면 strcpy가 되고 나중에는 wcscpy가 된다.

strcat, strlen등도 마찬가지이다. 즉, _tcslen, _tcscpy 이렇게 _tcs만 앞에 붙인다.

그런데 atoi함수같은 경우는 _ttoi, sprintf는 _stprintf이다.

즉 간혹 두 번 째에 t가 나올 경우가 있다.

- MSDN찾는 방법

strcpy : 위는 ansi, 두번째는 유니코드용, 밑에 TCHAR Routine에 _tcscpy가 나온다.

- API에 CreateWindow가 있다면 CreateWindowA는 ANSI용이고 CreateWindowW는 유니코드용이다. 이렇게 두개 함수가 있으므로 그냥 사용하면 된다.

- PTSTR과 LPTSTR은 같은 의미이다. 윈3.1때는 포인터에 NearPointer 2바이트가 있었고, 4바이트짜리 포인터가 있었다. 그래서 long형이 아닌 걸 만들어 놓았다.

지금은 세그먼트가 없으므로 LPCTSTR이나 PCTSTR차이가 없다. 그래서 PTSTR은 사용하지 않는다.

- char temp sz[100];

  for(i = 0; i<sizeof(sz); i++ )

이렇게 하면 틀린다. 왜냐하면 유니코드가 아니면 100이므로 괜찮지만 유니코드에서는 short int로 바뀌므로 200이 된다. 그래서 sizeof(sz)/sizeof(TCHAR)로 해줘야 한다.



♣ 윈도우 문자열 함수



- CompareString : 문자열 비교하는 api함수이다. c 런타임함수로 strcmp함수가 있으니까 이걸 쓰거나 _tcscmp를 쓰면 되는데 이 함수는 문법적으로는 유니코드를 지원하지만 논리적으로는 지원하지 않는다.

유니코드는 한글, 알파벳이 한꺼번에 모여있다. 그래서 같은 국가문자들끼리만 비교해주려면 CompareString함수를 써야한다. CompareString함수의 첫 번째 인자가 지역ID를 나타낸다. 즉, 이 인자를 사용해서 문자의 EMt을 검사함으로서 두 문자열을 비교하게 된다. 이런 동작은 단순히 숫자를 비교하는 C런타임함수보다 훨씬 의미가 더 있다. (C런타임함수 strcmp, wcscmp등은 문자열에서 코드 포인트의 값을 비교한다. 즉, 함수는 실제 문자의 의미를 무시하고 단순히 각 문자의 숫자 값을 검사한다.)

- 즉 문자열 대소비교할 때 같은 버퍼 안에 한글, 영문이 섞여있을 때는 이  API함수를 써야한다.

- CharLower, CharUpper함수들은 ansi가 없고 유니코드 전용함수들이다.

- 이런 함수들을 쓸때는 다음과 같이 코딩한다.


#ifdef _UNICODE

        CharLower();

#else

        tolower();

#endif


- IsTextUnicode : 텍스트가 ANSI인지 유니코드인지 결정하는 함수로서 참, 거짓을 반환한다. 즉, 버퍼가 유니코드인지 ANSI인지 판단해주는 함수이다.

PDA는 윈도우CE를 쓴다. 메모장에서 작성한걸 pda에서 쓰려면 먼저 유니코드로 변환해야 하는데 이럴 때 이 함수를 써서 유니코드인지 아닌지를 먼저 판단한다.

- DWORD IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);

- 함수인자로는 첫 번째 인자는 비교하고자 하는 버퍼주소인데 이때 버퍼문자열이 유니코드 문자열인지 ANSI 문자열인지 알지 못하므로 void포인터형이다.

두 번째 인자는 버퍼 바이트 수인데 역시 버퍼내용을 모르기 때문에 문자 카운트가 아닌 바이트의 카운트가 된다. 세 번째 인자는 비교하는 방법(옵션인데 null을 준다)으로 되어있다.

특히 이 함수는 통계적으로 판단한다. 즉 버퍼에 유니코드가 더 많으면 유니코드라고 판단해준다.


♧ 유니코드와 ANSI간의 문자열 변환


- MultiByteToWideChar : ANSI를 유니코드로 변환

- WideCharToMultiByte : 유니코드를 ANSI로 변환

- com은 os와 상관없이 반드시 유니코드를 써야한다.

- .Net : 실행가능한 개체를 만들자는게 목표이다. 실행가능한 개체란 소스상태가 아니고

컴파일된 상태를 말한다. 그래서 com도 같은 목표를 가지고 있다.

+ Recent posts