SJISからUTF-8への文字コード変換

最近、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を付加していません。

← ブログ一覧へ戻る