간단한 C++ 코드를 아래에 적어 보았습니다. 상당히 단순한 코드이므로, 주석과 설명은 생략합니다.
C++ 언어를 잘 모르시는 분은 그냥 이런게 있구나 정도만 이해해도 됩니다.
#pragma once
#include <stdio.h>
#pragma comment (lib, "ole32.lib") #pragma comment (lib, "Advapi32.lib")
#include <objbase.h> #include <windows.h> #include "Mlang.h"
#ifndef SAFE_RELEASE #define SAFE_RELEASE(x) if(x != NULL) { x->Release(); x = NULL; } #endif
unsigned __int32 DetectTextFileEncoding(const char* lpszFile);
int main(int argc, char** argv) { unsigned __int32 nCodePage = 0; char* pszFileName = NULL; int idx = 0; CoInitialize(0); for (idx = 0; idx < argc; ++idx) { switch (idx) { case 0: // break; case 1: // The full path of a specified file. pszFileName = *(argv + idx); default: break; } } nCodePage = DetectTextFileEncoding((const char*)pszFileName); CoUninitialize(); printf("Text File CodePage is [%d].n", nCodePage); return 0; }
unsigned __int32 DetectTextFileEncoding(const char* lpszFile) { HANDLE hFile = NULL; unsigned long dwFileSize = 0; void* pvData = NULL;
HGLOBAL hGlobal = NULL; unsigned long dwBytesRead = 0;
BOOL bIsUnicode = FALSE; BOOL bRead = FALSE;
IMultiLanguage2* pML2 = NULL; HRESULT hr = S_FALSE; __int32 nScores = 0;
DetectEncodingInfo encoding[10] = {0}; IStream* pstm = NULL;
unsigned __int32 nCodePage = 0;
try { // open file hFile = CreateFile(lpszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hFile) goto CLEAR_RESOURCE; // get file size dwFileSize = GetFileSize(hFile, NULL); if (-1 == dwFileSize) goto CLEAR_RESOURCE; // alloc memory based on file size hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); if (NULL == hGlobal) goto CLEAR_RESOURCE; pvData = GlobalLock(hGlobal); if (NULL == pvData) goto CLEAR_RESOURCE; // read file and store in global memory bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL); if (FALSE == bRead) goto CLEAR_RESOURCE; // create IStream* from global memory CreateStreamOnHGlobal(hGlobal, TRUE, &pstm); // determines if a buffer is likely to contain a form of Unicode(UTF-16 LE) text. bIsUnicode = IsTextUnicode((const void*)pvData, (__int32)dwBytesRead, 0); if (bIsUnicode == 1) { nCodePage = 1200; goto CLEAR_RESOURCE; } hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (void**)&pML2); if(FAILED(hr)) goto CLEAR_RESOURCE; nScores = sizeof(encoding) / sizeof(DetectEncodingInfo); hr = pML2->DetectCodepageInIStream(MLDETECTCP_NONE, 0, pstm, encoding, &nScores); nCodePage = encoding[0].nCodePage; } catch (…) { // DO Nothing!… } CLEAR_RESOURCE: SAFE_RELEASE(pstm); if (hGlobal != NULL) { if (pvData != NULL) GlobalUnlock(hGlobal);
GlobalFree(hGlobal); hGlobal = NULL; } if(hFile != NULL) { CloseHandle(hFile); hFile = NULL; } SAFE_RELEASE(pML2); return nCodePage; } |
코드를 보면 먼저 IsTextUnicode 함수를 이용하여 지정된 파일의 codepage 값이 유니코드(1200, UTF-16 Little Endian) 인지를 판단합니다. 만일 그렇지 않다면, DetectCodepageInIStream 함수를 이용합니다.
위의 코드에 대한 개선 사항이 있으면, 많은 제안을 바랍니다.