본문 바로가기

개발/mfc

[MFC] Cstring 유니코드 멀티바이트 UTF-8 문자열 인코딩 변환 모음(퍼옴)

반응형

 

 

여러 곳에서 퍼왔읍니다.

제가 모아 놓고 보기 위해...

 

============================ 이게 잘 되는 군...

CString -> const char *

1
2
3
CString aa = _T("123");
CStringA bb = (CStringA)aa;
Const char* dd = bb.GetBuffer();
 

const char * -> CString

1
2
3
const char* dd = "123";
CString aa;
aa = (CString)dd;

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

1. int -> CString 변환

CString szTest;

int nTemp = 100;

szTest.format(_T("%d"), nTemp); <-- 이러면 szTest로 int값이 들어옵니다.

(long 같은 경우는 "%d" 대신 "%l"로 바꿔주면 되겠죠? ^^)





2. CString -> int or long 등등.. 변환

CString szNum = _T("1234");

int nTestNum;

nTestNum = _ttoi(szNum); <-- int로 변환되어 저장됩니다. (atoi 도 있지만 _ttoi를 추천합니다)

 

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

Convert a std::string to char* in C++

https://www.techiedelight.com/convert-std-string-char-cpp/

 

#include <iostream>
#include <string>
 
int main()
{
    std::string str = "std::string to char*";
 
    char* c = const_cast<char*>(str.c_str());
    std::cout << c;
 
    return 0;
}

 

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

char *  --> std::string

 

char s[] = "test";                            //  char array s 정의

std::string sResultedString (s);      // char array s 를 변환 하여  std::string 변수 sResultedString 에 저장

 

 

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

 

CString => const char* 변환

> CString strTest = _T("test");

> const char* cTest = (char*)(LPCTSTR)strTest

또는

> CString strTest = _T("test");

> sprintf(sbuf,"%s\r\n", (const char*) (LPCTSTR)m_senddata);

 

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


> CString => const char* 변환

CString src = _T("test");
const char* dest;
dest = (CStringA)src;

>const char* => CString 변환
const char* src = "test";
CString dest;
dest = (CString)src;

CStringT type  : Declaration
----------------------------------------------------------------------------
CStringA        : An ANSI character type string with CRT support.
CStringW       : A Unicode character type string with CRT support.
CString          : Both ANSI and Inocode character types with CRT support.
----------------------------------------------------------------------------

 

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

CString => std::string

CString src = _T("test");                                     // CStrin 변수 src 정의

CT2CA CStringToAscii(sTextData);                   // CStrin 변수 src 를 변환 하여 ascii 변수 CStringToAscii 에 저장

std::string sResultedString (CStringToAscii);    // ascii 변수 CStringToAscii 를 변환 하여 std::string 변수 sResultedString 에 저장

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

std::string <-> CString 변환

#include <string>

// string 변수 s1 를 CString 변수 cStr1 으로 바꾸기
std::string s1;			
CString cStr1(s1.c_str());	
// 그리고,또한,  (CString)(s1.c_str())  이 CString 으로 바뀐거 이다.


// CString 변수 cStr2 를  string 변수 s2 으로 바꾸기
CString cStr2 = _T("HaHa");
std::string s2 = CT2CA(cStr2);

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

https://hizstory.tistory.com/9  .. 에서 퍼왔읍니다.

유니코드 -> 멀티바이트

1
2
3
4
5
wchar_t strUnicode[256] = {0,};
char    strMultibyte[256] = {0,};
wcscpy_s(strUnicode,256,L"유니코드");
int len = WideCharToMultiByte( CP_ACP, 0, strUnicode, -1, NULL, 0, NULL, NULL );   
WideCharToMultiByte( CP_ACP, 0, strUnicode, -1, strMultibyte, len, NULL, NULL );

stl이용

1
2
3
4
wstring strUni = L"유니코드";
int len = WideCharToMultiByte( CP_ACP, 0, &strUni[0], -1, NULL, 0, NULL, NULL );
string strMulti(len,0);
WideCharToMultiByte( CP_ACP, 0,  &strUni[0], -1, &strMulti[0], len, NULL, NULL );


멀티바이트 -> 유니코드

1
2
3
4
5
wchar_t strUnicode[256] = {0,};
char    strMultibyte[256] = {0,};
strcpy_s(strMultibyte,256,"멀티바이트");
int nLen = MultiByteToWideChar(CP_ACP, 0, strMultibyte, strlen(strMultibyte), NULL, NULL);
MultiByteToWideChar(CP_ACP, 0, strMultibyte, strlen(strMultibyte), strUnicode, nLen);

stl이용

1
2
3
4
string strMulti = "멀티바이트"; 
int nLen = MultiByteToWideChar(CP_ACP, 0, &strMulti[0], strMulti.size(), NULL, NULL);
wstring strUni(nLen,0);
MultiByteToWideChar(CP_ACP, 0, &strMulti[0], strMulti.size(), &strUni[0], nLen);


유니코드 -> UTF-8

1
2
3
4
wchar_t strUni[256] =L"유니코드";
char strUtf8[256] ={0,};
int nLen = WideCharToMultiByte(CP_UTF8, 0, strUni, lstrlenW(strUni), NULL, 0, NULL, NULL);
WideCharToMultiByte (CP_UTF8, 0, strUni, lstrlenW(strUni), strUtf8, nLen, NULL, NULL);


UTF-8 -> 유니코드로 변환

1
2
3
4
5
wchar_t strUnicode[256] = {0,};
char    strUTF8[256] = {0,};
strcpy_s(strUTF8,256,"utf-8글자..");// 이건 사실 멀티바이트지만 UTF8이라고 생각해주세요 -_-;;
int nLen = MultiByteToWideChar(CP_UTF8, 0, strUTF8, strlen(strUTF8), NULL, NULL);
MultiByteToWideChar(CP_UTF8, 0, strUTF8, strlen(strUTF8), strUnicode, nLen);


기본적으로 UTF-8로 변형할땐 유니코드 상태에서만 변형을 시켜야 된다!.

 만약 멀티 바이트를 UTF-8로 변형하고 싶을때에는
   멀티바이트 -> 유니코드(UTF-16) -> UTF-8 
UTF-8을 멀티바이트로 변형할때에는
   UTF-8 -> 유니코드(UTF-16) -> 멀티바이트..
 


그런데 위와 같은 방식은.. 윈도우 환경에서만 사용한다면 너무 복잡하다...

우리 위대하신 MS에서 만들어주신게 있는데..

1
2
3
4
5
6
7
8
9
10
11
12
#include // 요기에 정의..  이거하면 MFC사용안하고도 CString를 사용할수 있다
void main()
{
  wstring strUni = CA2W("멀티바이트를 유니코드로 변환");
  string strMulti = CW2A(L"유니코드를 멀티바이트로 변환");
  string strUTF8 = CW2A(L"유니코드를 UTF8로변환",CP_UTF8);
  //string에서 포인터 얻어오는게 c_str()이듯.
  //CA2W나 CW2A에서 포인터 얻어오는건 m_psz 이다..
  //그리고 CA2W CW2A는 기본적으로 CString 즉 (CAtlString)에 기반을 두고 고 있기때문에.
  //CString를 사용할때 가장 빠른다!!.
  // 만약 멀티 플레폼을 기준으로 한다면 CA2W는 사용 못함!
}


사용하기도 쉽고 속도면에서 MultiByteToWideChar,WideCharToMultiByte 보다 빠르다...

 

참고로 W는 wide , A는 ansi ,T는 TCHAR 이다.

 

펌 : http://icartsh.tistory.com/13

 

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

 

Unicode 상에서 CString을 std:string을 바꾸기

 
std::string strMain( CW2A( cstrMain.GetString() ) );

 

or

 

CString a = "ASDF";
std::string filename;
filename = CW2A(a);

 

 

펌 : http://chodalho.wordpress.com/2010/07/09/unicode-%EC%83%81%EC%97%90%EC%84%9C-cstring%EC%9D%84-stdstring%EC%9D%84-%EB%B0%94%EA%BE%B8%EA%B8%B0/

 

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

 

MultiByteToWideChar를 이용한 변환

MultiByteToWideChar()함수와 WideCharToMuliByte()함수를 사용해서 인코딩을 변환해 주는 것도 가능합니다. 이 두함수는 윈도우에서만 지원합니다. 따라서 OS 디펜던시가 없는 라이브러라 같은 것을 개발하신다면 이 두함수는 사용하실 수 없긴 하지만 많은 윈도우 개발자들이 사랑하는 함수죠. 

먼저 MBCS를 UTF-16으로 바꾸는 함수입니다.
 
int MultiByteToWideChar(
UINT CodePage, // 원본 스트링의 현재 인코딩 상태
DWORD dwFlags, // 0을 쓰면 된다.
LPCSTR lpMultiByteStr, // 변환하려는 문자열
int cbMultiByte, // -1을 넣으면 lpMultiByteStr의 길이를 알아서 계산
LPWSTR lpWideCharStr, // 변환된 유니코드를 저장할 공간
int cchWideChar // 유니코드를 저장할 공간의 사이즈
);

첫번째 인자에는 CP_ACP나 UTF-8둘중 하나를 넣으시면 됩니다. 
이함수는 특이한 기능이 있는데 맨마지막 인자에 0을 넣으면 필요한 wchar_t의 공간을 리턴합니다. 이를 이용해서 변환된 문자열에 딱맞는 공간을 할당 하실 수 있습니다. 다음은 반대로 UTF-16을 MBCS로 바꾸는 함수입니다.
 
int WideCharToMultiByte(
UINT CodePage, // 변환 타겟 인코딩
DWORD dwFlags, // 0
LPCWSTR lpWideCharStr, // 원본 스트링
int cchWideChar, // -1을 넣으면 원본 스트링 길이가 자동할당
LPSTR lpMultiByteStr, // 목적지
int cbMultiByte, // 목적지 사이즈
LPCSTR lpDefaultChar, // 실패시 사용
LPBOOL lpUsedDefaultChar // 실패 여부 판단
);

MultiByteToWideChar()함수와 거의 같은데 인자가 두개더 있습니다. lpDefaultChar인자는 인코딩이 실패했을 때 실패한 문자열 대신 사용될 문자열입니다. 보통 NULL로 지정하시면 됩니다. 마지막 인자 lpUsedDefaultChar는 변환에 실패한 문자가 하나라도 있을 때 TRUE를 리턴합니다. 유니코드는 MBCS보다 사이즈가 큰 집합이기 떄문에 MBCS에서 유니코드로의 변환은 실패할 일이 없지만 반대는 실패할 수도 있음을 기억하셔야 합니다.

 

TCHAR -> char

TCHAR temp[256]=L"Sample Text";
int strLen = 256;
char cTemp[256];
 
WideCharToMultiByte(CP_ACP, 0, temp, strLen, cTemp, strLen, NULL, NULL);
printf("%s" , cTemp);

char -> TCHAR

char buff[]="Sample Text";
TCHAR szUniCode[256]={0,};
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, charBuff, strlen(buff), szUniCode, 256);

 


USE_CONVERSION 를 이용해 변환

이 매크로를 이용하면 아주 쉽게 문자열을 변환할 수 있습니다. 사용법은 아래와 같습니다.
 
#include <atlconv.h> // 필요 include
#pragma comment(lib, "atls.lib") // 필요 lib
void SomeFunction()
{
USES_CONVERSION; // 먼저 적으셔야 합니다.
CAtlStringW wideStr[]=L"abc가나다";
CAtlStringA ansiStr;
ansiStr = W2A(widechar); // UTF-16을 MBCS로 바꿉니다.
}

W2A말고도 여러 매크로를 제공하는데요. 아래와 같습니다. (const 변환용 매크로 제외)
매크로설명
A2W LPCSTR -> LPWSTR
W2A LPCWSTR -> LPSTR
A2T LPCSTR -> LPTSTR
T2A LPCTSTR -> LPSTR
T2OLE LPCTSTR -> LPOLESTR
OLE2T LPCOLESTR -> LPCSTR

이 매크로는 사용하기엔 편하지만 UTF8을 UTF-16 으로 변환하는데 쓰실 수 없습니다. 또 주의 해야 할 것이 있는데요. 각 매크로를 사용할 떄 변환에 필요한 공간이 스택에 할당된다는 점입니다. 따라서 실제적으로 아래를 주의 하셔야 합니다.
  • 너무 큰 스트링을 변환하고 시도하면 스택 오버 플로가 날 수 있습니다.
  • 루프 안에서 과도한 변환을 시도하면 스택 오버 플로가 날 수 있습니다.
  • 스택에서 잡힌 공간이기 때문에 매크로의 결과를 리턴시키면 안됩니다.
  •  

CA2W계열의 클래스를 이용한 변환

USE_CONVERSION 를 이용한 변환이 편하긴 한데 위에서 말한대로 문제가 좀 있기 때문에 ATL 7.0이후 CATW계열의 클래스들이 새로 등장했습니다. 이 아이는 클래스인데다가 기본적으로 128바이트의 내부 버퍼를 가지고 있고(변경 가능 합니다만..), 이보다 크면 알아서 힙에 동적할당을 해주는 똑똑한 놈입니다.
 
#include <atlconv.h> // 필요 include
#pragma comment(lib, "atls.lib") // 필요 lib
void SomeFunction()
{
CA2W p ("123가나다"); // 클래스 선언
CA2WEX<256> p2 ("123마바사"); // EX를 붙이면 내부 버퍼 사이즈를
// 변경시킬 수 있습니다만 새로운
// 사이즈별로 코드가 새로 생깁니다.
CAtlStringW str(p); // p가 LPWSTR을 리턴합니다.
CAtlStringW str2 = p2; // p2가 LPWSTR을 리턴합니다.
}

이런식으로 사용합니다. 주의할 점은 역시 위 코드에서 보이는 p를 리턴 시키면 안됩니다.(당연한 이야기지만) CA2W외 그밖의 클래스 들은 아래와 같습니다. (아래 목록은 cosnt와 버퍼 사이즈를 변경할 수 있는 EX가 붙어 있는 것들이 제외 되었습니다.)
클래스설명
CA2W LPCSTR -> LPWSTR
CW2A LPCWSTR -> LPSTR
CA2T LPCSTR -> LPTSTR
CT2A LPCTSTR -> LPSTR
CT2OLE LPCTSTR -> LPOLESTR
COLE2T LPCOLESTR -> LPCSTR
아쉬운 것이 있다면 UTF-8로의 변환을 지원하는 클래스가 있었다면 좀더 좋았을 텐데 이점이 조금 아쉽습니다.

참조 : http://cafe.naver.com/newchany.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=625

Tip : atlconv.h 를 인클루드 했는데도 CA2W 클래스를 찾을 수 없다는 컴파일 오류가 나온다면 atlconv.h 대신 atlbase.h 를 인클루드 하면 컴파일 오류를 해결할 수 있다.

추천 사용 방법
#include <atlbase.h>
#include <string>
inline std::wstring _A2U( IN CONST CHAR *str ) { ATL::CA2W ca2w( str ); return std::wstring( ca2w ); }
inline std::string _U2A( IN CONST WCHAR *str ) { ATL::CW2A cw2a( str ); return std::string( cw2a ); }
#define A2U( str ) (WCHAR *)_A2U( str ).c_str()
#define U2A( str ) (CHAR *)_U2A( str ).c_str()

 

 

< 사용후기 >

 - 아래 함수 이거 너무 편해서 좋은데, 웬만한 Loop 돌면 심심하면 STack OverFlow 발생하네요.

 - 나중에 PG이 왜 죽는지도 모르는... Data 양에 따라서 PG에 Bug / Error 가 발생하는 찾기 힘든 Bug를 양산할 수 있음돠~ ㅠㅠ

 

USES_CONVERSION;

W2A();

A2W();

반응형