본문 바로가기

WinAPI

[WinAPI] 게임 프레임워크 - 5. PathManager, 유니코드와 멀티바이트

PathManager는 프로젝트 내 파일을 읽거나 쓸 때 경로가 필요할 때 사용한다.

 

wchar_t strPath[MAX_PATH] = {};
	GetModuleFileName(NULL, strPath, MAX_PATH);

	for (int i = lstrlen(strPath) - 1; i >= 0; --i)
	{
		if (strPath[i] == '/' || strPath[i] == '\\')
		{
			memset(strPath + (i + 1), 0, sizeof(wchar_t)*(MAX_PATH-(i+1)));
			break;
		}
	}

	m_mapPath.insert(make_pair(ROOT_PATH, strPath));

 

PathManager::Init에서는 저장할 경로를 m_mapPath에 저장한다. 위 코드는 기본 경로 ROOT_PATH를 저장하는데, 먼저 GetMoudleFileName함수는 strPath에 프로그램 실행파일의 경로를 저장한다. 그리고 memset 으로 strPath가 / 나 \를 만난 이후부터 0으로 지워버린다. 예로 실행파일 경로가 "C:\Bin\Debug.exe"라면 "C:\Bin\"이 ROOT_PATH가 된다. 같은 방식으로 텍스쳐 파일을 저장하는 TEXTURE_PATH나 세이브파일을 저장하는 DATA_PATH도 m_mapPath에 저장한다.

 

const char* CPathManager::FindPathMultiByte(const string& strKey)
{
	const wchar_t* pPath = FindPath(strKey);

	if (!pPath)
		return NULL;

	memset(m_strPath, 0, MAX_PATH);

	WideCharToMultiByte(CP_ACP, 0, pPath, -1, m_strPath,
		lstrlen(pPath), 0, 0);

	return m_strPath;
}

 

FindPathMultiByte는 fopen_s 같은 파일 관련 함수에서 경로가 필요할 때 멀티바이트 문자열이 필요하기 때문에 const wchar_t*를 const char*로 바꿔준다. WideCharToMultiByte 함수를 사용한다. 이 과정은 유니코드 문자열을 멀티바이트 문자열로 변환하는 것이다. 나는 유니코드와 멀티바이트, 그리고 아스키 코드 문자의 차이에 대한 것이 궁금해져 조사해보았다.

 

아스키코드는 최초에 만들어진 문자 코드로 1바이트이며 한글이나 일어 등 2바이트로 표현가능한 언어들을 표현할 수 없다. 그래서 아스키  코드에 다른 문자를 포함해서 만든 것이 멀티바이트이다. 멀티바이트 문자는 한글이나 일어 등을 표현할 수 있고 언어에 따라 1바이트가 되기도 하고 2바이트가 되기도 한다. 또한 특정 문자 집합마다 코드 페이지가 있어 한글을 일어 코드 페이지로 읽으면 깨져 보인다. 마지막으로 유니코드는 문자당 2바이트를 할당하며 모든 문자를 표현 가능하다. 타입은 wchar_t 를 사용한다.

 

wchar_t *ws1 = L"Hello, world!"; 

 

wchar_t 문자열은 위와 같이 앞에 L을 붙여 표시해준다. 유니코드 문자열은 함수도 w가 붙은 별도의 함수를 사용해야 한다.