最近、Windows標準のShift-JISから、Web標準となっている(?)UTF-8への文字コード変換が必要な場合がちらほら出てきている。
マルチプラットフォームでデータをやり取りする場合なんかでもUTF-8が結構使われていたりする。
こういうコード変換なんかは、テキストエディタ等を使えば、簡単に変換できる。
最近ではメモ帳でもUTF-8保存ができるようになったし。
でも、このコード変換が100個、1000個、と数が増えてくると手作業は無理。
そんな訳で、VC++(非.NET)でSJISからUTF-8に変換するプログラムを作ってみることにした。
# バッチで利用したいという理由もあったんで。
しかし、SJISからUTF-8に直接変換するようなWin32APIは用意されていないことに気付いた。
C#やVB.NETならきっと一発で変換できるんだろうけど(多分)。
調べてみると、シフトJISからUTF-8に変換するためには、一回Unicodeに変換させる必要があることが分かった。
あぁ面倒。
まず、MultiByteToWideCharを使用し、SJISからUnicodeへ。
次に、WideCharToMultiByteを使用し、UnicodeからUTF-8へ。
出来上がったプログラムソースは以下のとおり。
#include "stdafx.h" #include "Windows.h" #define NUM_OF_LINE_CHARS 200 int _tmain(int argc, _TCHAR* argv[]) { FILE *targetFile,*tmpFile; wchar_t wszTmpFile[_MAX_PATH]; wchar_t wszBuf[NUM_OF_LINE_CHARS]; char zsLineIn[NUM_OF_LINE_CHARS]; char zsLineOut[NUM_OF_LINE_CHARS * 2]; wsprintf(wszTmpFile,_TEXT("%s.tmp"),argv[1]); memset(zsLineOut,0x00,NUM_OF_LINE_CHARS * 2); if(argc!=2){ printf_s("\nusage: %S ファイル名\n",argv[0]); return -1; } // 一時ファイルをオープン if( _wfopen_s( &tmpFile, wszTmpFile, L"w" ) != 0 ) { printf_s( "%S:一時ファイル作成エラー(%S)\n", argv[0], wszTmpFile); return -1; } // 指定したファイルをオープン if( _wfopen_s( &targetFile, argv[1], L"r" ) == 0 ) { // EOFまで繰り返し while(!feof(targetFile)){ // 行単位で読み込み if(fgets(zsLineIn,NUM_OF_LINE_CHARS,targetFile)!=NULL) { // SJIS → Unicode if(MultiByteToWideChar( CP_ACP, 0, (const char *)zsLineIn, -1, wszBuf, NUM_OF_LINE_CHARS) == 0) { printf_s( "%S:変換エラー(MultiByteToWideChar)\n", argv[0]); return -1; } // Unicode → UTF8 if(WideCharToMultiByte( CP_UTF8, 0, wszBuf, -1, (char *)zsLineOut, NUM_OF_LINE_CHARS, NULL, NULL) == 0) { printf_s( "%S:変換エラー(WideCharToMultiByte)\n", argv[0]); return -1; } fputs(zsLineOut,tmpFile); } } _fcloseall(); // ファイル置き換え _wremove(argv[1]); _wrename(wszTmpFile,argv[1]); }else{ printf_s( "%S:ファイルオープンエラー(%S)\n", argv[0], argv[1]); return -1; } return 0; }
出来上がったexeファイルはコマンドプロンプトより実行する。
第一引数に、コード変換させたいSJISファイル名を指定する。
第一引数に指定したファイルは、UTF-8ファイルに書き換えられる。
※このプログラムで出力するUTF-8ファイルは、BOMを付加していません。