Shift-JIS のテキストファイルを UTF-8 に変換する

システムロケールが English になっている場合などの英語環境で cpp などのソースコードが Shift-JIS でマルチバイト文字が含まれている場合、Visual Studio での表示が文字化けたり、コンパイルが通らなくなることがあります。このときソースコードの形式を「ボム付きUTF-8」や「Unicode」に変換することでビルドができるようになります。

今回は Shift-JIS のソースコードを一括で UTF-8 に変換するコードを書いたので紹介します。

プロジェクトのダウンロード

BOOL CheckCodePage(LPCSTR lpszString, int nCodePage)
{
	int nLength = MultiByteToWideChar(nCodePage, 0, lpszString, -1, 0, 0);
	LPWSTR lpszStringW = (LPWSTR)GlobalAlloc(GPTR, nLength * sizeof(WCHAR));
	MultiByteToWideChar(nCodePage, 0, lpszString, -1, lpszStringW, nLength);
	nLength = WideCharToMultiByte(nCodePage, 0, lpszStringW, -1, 0, 0, 0, 0);
	LPSTR lpszNewStringA = (LPSTR)GlobalAlloc(GPTR, nLength);
	WideCharToMultiByte(nCodePage, 0, lpszStringW, -1, lpszNewStringA, nLength, 0, 0);
	GlobalFree(lpszStringW);
	BOOL bReturnValue = (lstrcmpA(lpszString, lpszNewStringA) == 0);
	GlobalFree(lpszNewStringA);
	return bReturnValue;
}

BOOL ShiftJIS2UTF8(LPCTSTR lpszFilePath, BOOL bBom = TRUE)
{
	if (!lpszFilePath) return FALSE;
	if (!PathFileExists(lpszFilePath)) return FALSE;

	HANDLE hFile = CreateFile(lpszFilePath, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hFile == INVALID_HANDLE_VALUE) return FALSE;

	const int nFileSize = GetFileSize(hFile, 0);
	if (nFileSize == 0)
	{
		CloseHandle(hFile);
		return FALSE;
	}

	LPSTR lpszText = (LPSTR)GlobalAlloc(GPTR, GetFileSize(hFile, 0) + 1);
	DWORD dwReadSize;
	ReadFile(hFile, lpszText, nFileSize, &dwReadSize, 0);
	CloseHandle(hFile);

	// BOM が付いている場合は既にUTF-8に変換されているとみなす
	if (lpszText[0] == 0xEF && lpszText[0] == 0xBB && lpszText[0] == 0xBF)
	{
		GlobalFree(lpszText);
		return FALSE;
	}

	// 既に UTF-8 の場合
	if (CheckCodePage(lpszText, CP_UTF8))
	{
		GlobalFree(lpszText);
		return FALSE;
	}

	// ANSI コードページではない場合
	if (!CheckCodePage(lpszText, CP_ACP))
	{
		GlobalFree(lpszText);
		return FALSE;
	}

	hFile = CreateFile(lpszFilePath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		GlobalFree(lpszText);
		return FALSE;
	}

	int nLength = MultiByteToWideChar(932, 0, lpszText, -1, 0, 0);
	LPWSTR lpszStringW = (LPWSTR)GlobalAlloc(GPTR, nLength * sizeof(WCHAR));
	MultiByteToWideChar(932, 0, lpszText, -1, lpszStringW, nLength);

	GlobalFree(lpszText);

	nLength = WideCharToMultiByte(CP_UTF8, 0, lpszStringW, -1, 0, 0, 0, 0);
	LPSTR lpszNewStringA = (LPSTR)GlobalAlloc(GPTR, nLength);
	WideCharToMultiByte(CP_UTF8, 0, lpszStringW, -1, lpszNewStringA, nLength, 0, 0);

	GlobalFree(lpszStringW);

	DWORD dwWriteSize;
	if (bBom)
	{
		BYTE byBom[] = { 0xEF, 0xBB, 0xBF };
		WriteFile(hFile, byBom, 3, &dwWriteSize, 0);
	}

	WriteFile(hFile, lpszNewStringA, nLength - 1, &dwWriteSize, 0);

	GlobalFree(lpszNewStringA);

	CloseHandle(hFile);

	return TRUE;
}

スポンサーリンク
広告1
広告1

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
広告1