2020년 4월 11일 토요일

MFC URLDecode 처리

오늘 이야기할 내용은 웹에서 넘겨져온 데이터를 처리할때 한글이 깨지거나 특수문자등이 깨지지 않게 처리 데이터를 받아 내리는 방법중 URLEncode 되어서 넘겨진 데이터를 DeCode 하는 방법을 이야기 할까 합니다.

URLEncode 하는 방법은 아래 링크로 확인하세요.

물론 웹에서 넘겨온 데이터가 URLEncode로 처리가 되어진 문자열 이어야 합니다.

일단 소스부터 볼께요.


BYTE ConByte(const BYTE& uc) { return uc > 57 ? uc - 55 : uc - 48; }

CString ConvertURLDecode(CString sOrg)
{
 CString sOut;
 const int nLen = sOrg.GetLength() + 1;
 register LPBYTE pOutTmp = NULL;
 LPBYTE pOutBuf = NULL;
 register LPBYTE pInTmp = NULL;
 LPBYTE pInBuf = (LPBYTE)sOrg.GetBuffer(nLen);
 //alloc out buffer
 pOutBuf = (LPBYTE)sOut.GetBuffer(nLen);

 if (pOutBuf)
 {
  pInTmp = pInBuf;
  pOutTmp = pOutBuf;
  // do encoding
  while (*pInTmp)
  {
   if ('%' == *pInTmp)
   {
    pInTmp++;
    *pOutTmp++ = (ConByte(*pInTmp) % 16 << 4) + ConByte(*(pInTmp + 1)) % 16;
    pInTmp++;
   }
   else
    *pOutTmp++ = *pInTmp;
   pInTmp++;
  }
  *pOutTmp = '\0';
  sOut.ReleaseBuffer();
 }
 sOrg.ReleaseBuffer();

 return sOut;
}
[위 소스는 Visual Studio 2017, Window 10 64bit 환경에서 빌드 되었습니다.]

소스를 보시면 아시겠지만 URLDecode는 헥사로 변환된 문자열을 다시 바이트 문자열로 변환하는 코드 입니다.

웹에서 넘겨진 데이터가 URLEncode로 변환 되어졌을경우 만든는 프로그램 환경이 UTF-8 환경이면 Decode 코드로만 처리가 되지만 Ansi 환경일 경우에는 UTF8 을 Ansi 로 바꾸는것을 Decode 하고 난후 처리 해야 한글 같은것을 정상적으로 처리 하실수 있습니다.

아래 링크도 필요하시면 확인 하시기 바랍니다.

그럼 ^^

MFC URLEncode 처리

오늘 이야기할 내용은 MFC 에서 웹으로 데이터를 보낼때 한글이 깨지거나 특수 문자 등을 처리 할때 깨지지 않고 보내기 위해서 보내는 방법중 URLEncode 처리 방법을 이야기 할까 합니다.

라이브러리를 설치 해서 쓰면 되지만 라이브러리 때문에 빌드가 안되거나 하는 상황이 많기 때문에 직접 구현 하는 방법으로 안내 할까 합니다.

​일단 소스 부터 볼께요.




BYTE ConHex(const BYTE& uc){ return uc > 9 ? uc + 55 : uc + 48; }

CString ConvertURLEncode(CString sOrg)
{
 CString sOut;
 const int nLen = sOrg.GetLength() + 1;
 register LPBYTE pOutTmp = NULL;
 LPBYTE pOutBuf = NULL;
 register LPBYTE pInTmp = NULL;
 LPBYTE pInBuf = (LPBYTE)sOrg.GetBuffer(nLen);
 //alloc out buffer
 pOutBuf = (LPBYTE)sOut.GetBuffer(nLen * 3);

 if (pOutBuf)
 {
  pInTmp = pInBuf;
  pOutTmp = pOutBuf;
  // do encoding
  while (*pInTmp)
  {
   if (isalnum(*pInTmp) || '-' == *pInTmp || '_' == *pInTmp || '.' == *pInTmp)
    *pOutTmp++ = *pInTmp;
   else
   {
    *pOutTmp++ = '%';
    *pOutTmp++ = ConHex(*pInTmp >> 4);
    *pOutTmp++ = ConHex(*pInTmp % 16);
   }
   pInTmp++;
  }
  *pOutTmp = '\0';
  sOut.ReleaseBuffer();
 }
 sOrg.ReleaseBuffer();

 return sOut;
}
[위 소스는 Visual Studio 2017, Window 10 64bit 환경에서 빌드 되었습니다.]

소스를 보시면 아시겠지만 URLEncode 는 숫자,영문,몇개의 특수문자 외의 문자열은 HEX 값으로 변환하여 전달하는 방법입니다.

물론 받는 쪽에서는 DeCode를 해서 풀어야 정상적인 문자열로 확인 할수 있습니다.

웹이랑 데이터를 주고 받기 위해서는 단순히 URLEncode 만 호출 해서 해결 할수 있지만 개발되는 프로그램 플랫폼 환경이 Ansi 환경이면 UTF8로 변환 한후 그것을 다시 URLEncode로 변환하여 전달 해야 정상적으로 웹에 전달이 됩니다.

아래 링크도 확인 하시기 바랍니다.
https://ansur.blogspot.com/2020/04/mfc-ansi-utf8.html

그럼 ^^

2020년 4월 4일 토요일

MFC UTF8 문자열 Ansi 문자열 변환.

Ansi 문자열을 UTF8 문자열로 변환하는것은 아래 포스트를 확인하시면 됩니다.
https://ansur.blogspot.com/2020/04/mfc-ansi-utf8.html

이번에 이야기 할것은 웹에서 데이터가 들어올때는 UTF8 코드 페이지로 기본적으로 들어 올겁니다.
이떄 가지고 계신 시스템이 Ansi 코드 페이지로 운영이 되시면 문자열 변환을 해야 합니다.
그 처리 방법에 대한 코드를 설명 하고자 합니다.

일단 UTF8 문자열을 Ansi 문자열로 변환 하는 코드 입니다.


BSTR    bstrWide;
char*   pszAnsi;
int     nLength;

nLength = MultiByteToWideChar(CP_UTF8, 0, sUTF8Str, lstrlen(sUTF8Str) + 1, NULL, NULL);
bstrWide = SysAllocStringLen(NULL, nLength);
MultiByteToWideChar(CP_UTF8, 0, sUTF8Str, lstrlen(sUTF8Str) + 1, bstrWide, nLength);

nLength = WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, NULL, 0, NULL, NULL);
pszAnsi = new char[nLength];
WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, pszAnsi, nLength, NULL, NULL);
SysFreeString(bstrWide);

위 코드와 같이 변환을 하시면 마지막에 pszAnsi 포인터에 담긴 변수의 값을 시스템 내부에서 사용 하시면 됩니다.

코드의 처리는 먼저 UTF8로 들어온 문자열을 UniCode 형태로 변환을 합니다.
그다음 UniCode로 변환된 값을 다시 멀티 바이트로 변환 하는데 이떄 Ansi 코드 페이지를 이용하여 변환 하는 방식입니다.

그럼 ^^;

MFC Ansi 문자열 UTF8 문자열 변환

MFC는 오래된 플랫폼이죠.

그래도 이걸로 먹고 산지가 오래 되어서 ^^
요즘들어 웹이랑 데이터를 주고 받는 일이 많다 보니 웹에서는 UTF8을 기본 문자 코드로 쓰기 때문에 MFC 이전 프로젝트를 쓰시는 한글 같은것을 주고 받을때 문제가 생기기 마련입니다.​

일단 Ansi 문자열을 UTF8 문자열로 변환 하는 코드 입니다.


int  nLength, nLength2;
BSTR bstrCode; 
char* pszUTFCode = NULL;

nLength = MultiByteToWideChar(CP_ACP, 0, sAnsiStr, lstrlen(sAnsiStr), NULL, NULL); 
bstrCode = SysAllocStringLen(NULL, nLength); 
MultiByteToWideChar(CP_ACP, 0, sAnsiStr, lstrlen(sAnsiStr), bstrCode, nLength);

nLength2 = WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, 0, NULL, NULL); 
pszUTFCode = (char*)malloc(nLength2+1); 
WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, nLength2, NULL, NULL);  

위 코드와 같이 변환을 하시면 마지막에 pszUTF8 포인터에 담긴 변수의 값을 웹쪽에 전달을 하면 UTF8 형태의 문자열로 전달할수 있습니다.

코드의 처리는 먼저 멀티바이트 Ansi 코드를 UniCode로 변환을 합니다.
그다음 UniCode로 변환된 값을 다시 멀티 바이트로 변환 하는데 이때 UTF8 코드 페이지를 이용하여 변환 하는 방식 입니다.

그럼 ^^;

2020년 4월 2일 목요일

Window C++ 가용 메모리 확보하기 (Not MFC)

https://ansur.blogspot.com/2020/04/window-c.html

여기에서 MFC 기반으로 사용된 가용 메모리 확보를 알아 보았습니다.
하지만 MFC를 쓰지 않고 사용 하는 방법을 알아 보겠습니다.

일단 코드 부터 확인 하겠습니다.


#include <new>

MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);

UINT nUsageMemSize = status.ullAvailVirtual;
double fMemPercent = 0.0;

while (true)
{  
 LPBYTE lpChk = new (std::nothrow) BYTE[nUsageMemSize];
 if (lpChk == nullptr)
 {
  fMemPercent = fMemPercent == 0.0 ? 0.1 : fMemPercent*0.1;
  nUsageMemSize = (UINT)(status.ullAvailVirtual * fMemPercent);
  if (nUsageMemSize < nMinBuff)
   nUsageMemSize = nMinBuff;
 }
 else
 {
  delete[] lpChk;
  break;
 }
}

<위 코드는 Visual Studio 2013 Window 10 64bit에서 테스트 하였습니다>

기존의 포스팅 된 내용은 try catch 를 이용하여 처리를 하였는데 위 처리 방법은 std::nothrow 를 이용하여
exception 을 발생 시키지 않는 데신 메모리를 할당할수 없으면 nullptr 을 리턴 하는 점 입니다.


그 이후 처리 방법은 이전 포스팅을 보시면 될거 같네요 ^^

2020년 4월 1일 수요일

Window C++ 가용 메모리 확보하기

C++ 코드를 만드실때 샘플을 보시면 파일을 복사 하거나 메모리를 확보 할때 버퍼 용량을
512Byte 또는 1024Byte 로 제한된 것을 볼수 있습니다.
이전에 만들어진 코드를 재활용을 하다 보니 문제는 없으나 대용량 파일을 처리 하거나 메모리를 운영시에는 작은 사이즈의 버퍼를 운영 하다 보니 속도의 이슈가 생기기 마련 입니다.
윈도우에서 사용할수 있는 가용 버퍼를 확인 하는 방법을 알아 보겠습니다.


일단 코드 부터 확인 하겠습니다.


MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
const UINT MINBUFF = 1024;
UINT nUsageMemSize = status.ullAvailVirtual;
float fMemPercent = 0.0;
  
while (true)
{
 try
 {
  LPBYTE lpChk = new BYTE[nUsageMemSize];
  if (lpChk != NULL)
  {
   delete[] lpChk;
   break;
  }
 }
 catch (CMemoryException* e)
 {
  fMemPercent = fMemPercent == 0.0 ? 0.1 : fMemPercent*0.1;
  nUsageMemSize = status.ullAvailVirtual * fMemPercent;
  if (nUsageMemSize < MINBUFF)
   nUsageMemSize = MINBUFF;
 }
}

TRACE(_T("nUsageMemSize [%u]"), nUsageMemSize);

<위 코드는 Visual Studio 2013 Window 10 64bit에서 테스트 하였습니다>
위코드를 실행 하시면 현재 프로그램에서 가용할수 있는 버퍼를 찾으실수 있습니다.
동작 방법은 윈도우 SDK 에서 제공하는 MEMORYSTATUSEX 구조체를 활용합니다.




위 GlobalMemoryStatusEx 함수를 이용하시면 현재 시스템의 메모리 정보를 얻어 옵니다.
제가 활용한 멤버는 현재 프로세스에 할당된 가용 메모리 항목입니다. (ullAvailVirtual)
위 항목으로 메모리 용량을 확보 하면 메모리가 할당이 안될수 있기 때문에 Exception 코드를 걸어 둬서
메모리 용량 확보에 실패 하면 원래 크기의 0.1 만큼 할당하는 로직입니다. 반복적으로 메모리 용량 확보에 실패시
0.1=>0.01=>0.001 이렇게 지속적으로 작게 메모리를 할당하여 얻을수 있는 크기를 얻어 옵니다.


대용량 파일을 직접 복사하는 코드를 구현 하실때 또는 기타 사항으로 처리 하시면 좋을듯 하네요. 그럼 ^^