인코딩 종류는 엄청 많지만 텍스트 파일을 저장할 때는 ANSI, UTF-8, UTF-8(BOM), UTF-16 LE, UTF-16 BE 이 5가지를 주로 사용합니다.
🔽 인코딩이나 BOM에 대해 궁금하시다면 아래 글을 참고해주세요.
유니코드 인코딩 BOM(Byte Order Mark) 정리
문자 인코딩(Encoding)이란? 문자 인코딩은 사용자가 입력한 문자나 기호를 컴퓨터가 이해할 수 있는 것으로 만드는 것을 의미합니다. 1. 인코딩의 종류 텍스트 파일을 저장할 때 인코딩 형식을 선
dev-drive.tistory.com
MFC 프로젝트에서는 멀티바이트, 유니코드 세팅을 할 수 있고 txt 파일도 여러가지 인코딩이 존재하니 이런걸 다 처리해주지 않으면 특정 경우에서는 글자가 깨질 수 있겠죠.
-> 예를들어 멀티바이트 프로젝트에서 UTF-16파일을 읽고 후처리를 하지않으면 제대로 된 글자를 얻을 수 없습니다.
🔽 그러면 바로 CFile로 txt파일의 인코딩을 구분해서 읽는 방법에 대해 알아보겠습니다.
enum encoding { ANSI, UTF8, UTF8_BOM, UTF16_LE, UTF16_BE };
encoding enc = ANSI;
CString sContent;
CString sFilePath = _T("txt파일 경로");
CFile hFile;
if (hFile.Open(sFilePath, CFile::modeRead))
{
int nLen = (int)hFile.GetLength();
TCHAR* pData = new TCHAR[nLen + 2];
memset(pData, 0, (nLen + 2));
LONG nReadSize = hFile.Read(pData, nLen);
if (nReadSize == nLen)
{
// 인코딩 검사
char* szBOM = new char[3];
memset(szBOM, 0, 3);
memmove(szBOM, (char*)pData, 3);
unsigned char littleEndianBOM[] = { 0xFF, 0xFE };
unsigned char bigEndianBOM[] = { 0xFE, 0xFF };
unsigned char utf8BOM[] = { 0xEF, 0xBB, 0xBF };
unsigned char* lpHeader = (unsigned char*)szBOM;
if (lpHeader[0] == littleEndianBOM[0] && lpHeader[1] == littleEndianBOM[1])
enc = encoding::UTF16_LE;
else if (lpHeader[0] == bigEndianBOM[0] && lpHeader[1] == bigEndianBOM[1])
enc = encoding::UTF16_BE;
else if (lpHeader[0] == utf8BOM[0] && lpHeader[1] == utf8BOM[1] && lpHeader[2] == utf8BOM[2])
enc = encoding::UTF8_BOM;
else
{
// 위 3가지 경우가 아닐 경우 파일 내용을 분석해 UTF8과 Ansi를 구분함
if (IsUTF8((const void*)pData, nLen))
enc = encoding::UTF8;
}
// 인코딩 처리
WCHAR* pBuffer = new WCHAR[nLen + 2];
memset(pBuffer, 0, nLen + 2);
switch (enc)
{
case ANSI:
{
int nLength = MultiByteToWideChar(CP_ACP, 0, (char*)pData, nLen, NULL, NULL);
memset(pBuffer, 0, sizeof(WCHAR)* (nLength + 1));
MultiByteToWideChar(CP_ACP, 0, (char*)pData, nLen, pBuffer, nLength);
break;
}
case UTF8:
{
int nLength = MultiByteToWideChar(CP_UTF8, 0, (char*)pData, nLen, NULL, NULL);
memset(pBuffer, 0, sizeof(WCHAR)* (nLength + 1));
MultiByteToWideChar(CP_UTF8, 0, (char*)pData, nLen, pBuffer, nLength);
break;
}
case UTF8_BOM:
{
int nLength = MultiByteToWideChar(CP_UTF8, 0, (char*)pData + 3, nLen - 3, NULL, NULL);
memset(pBuffer, 0, sizeof(WCHAR)* (nLength + 1));
MultiByteToWideChar(CP_UTF8, 0, (char*)pData + 3, nLen - 3, pBuffer, nLength);
break;
}
case UTF16_LE:
{
wcscpy_s(pBuffer, nLen + 2, (WCHAR*)pData + 1);
break;
}
case UTF16_BE:
{
wcscpy_s(pBuffer, nLen + 2, (WCHAR*)pData + 1);
// Swap Byte
WCHAR ch;
WCHAR* tmpBuf = new WCHAR[nLen + 2];
memset(tmpBuf, 0, nLen + 2);
memmove(tmpBuf, pBuffer, nLen);
int nPos = 0;
while (nPos <= nLen)
{
ch = pBuffer[nPos];
if (ch == 0x00)
{
memcpy(pBuffer, tmpBuf, nLen);
break;
}
tmpBuf[nPos++] = MAKEWORD(HIBYTE(ch), LOBYTE(ch));
}
delete[] tmpBuf;
break;
}
default:
break;
}
sContent = (CString)pBuffer;
delete[] szBOM;
delete[] pData;
delete[] pBuffer;
}
}
hFile.Close();
* 멀티바이트, 유니코드 프로젝트 세팅과 상관 없이 모두 읽을 수 있는 소스입니다.
* UTF-8에서 + 3, UTF-16에서 + 1 해주는 이유는 앞부분에 있는 BOM을 제외하고 읽기 위함입니다. BOM이 필요하다면 + 부분 지우고 처리하면 됩니다.
* UTF16-BE는 Byte Order를 바꿔주기 위한 작업을 진행했습니다.
* txt파일을 Write할때는 반대로 Byte Order를 먼저 Write하고 뒤에 내용을 넣어주면 됩니다.
🔽 IsUTF8 함수에 대한 내용은 아래 글을 참고해주세요.
[C++/MFC] 텍스트 파일의 인코딩 확인하는 방법
유니코드 인코딩 BOM(Byte Order Mark) 정리 문자 인코딩(Encoding)이란? 문자 인코딩은 사용자가 입력한 문자나 기호를 컴퓨터가 이해할 수 있는 것으로 만드는 것을 의미합니다. 1. 인코딩의 종류 텍스
dev-drive.tistory.com
🔽 txt파일 인코딩 구분 읽기, 쓰기 기능 추가해서 만들어본 프로그램입니다. 메모장이랑 다를게 없긴한데 필요하신분들은 다운받아서 사용하세요
'C++, MFC' 카테고리의 다른 글
[MFC] 프로그램 내부에서 다른 프로그램(exe, msi) 설치하는 방법 / exe, msi 설치 옵션 (1) | 2022.09.29 |
---|---|
[MFC] 프로세스간 통신 (Inter Process Communication, IPC) 방법 설명 (0) | 2022.09.27 |
[C++/MFC] 멀티바이트, 유니코드 개념 정리 / 문자열 변환 방법 (1) | 2022.09.19 |
[C++/MFC] 텍스트 파일의 인코딩 확인하는 방법 (0) | 2022.09.16 |
[MFC] 재배포 패키지 없이 프로그램 배포하는 방법 (0) | 2022.08.29 |
댓글