読者です 読者をやめる 読者になる 読者になる

SQLite2からSQLite3にデータベースをバージョンアップするプログラムをコマンドラインツールとC#で作るときにはまった件

Windows+C#でSQLite2からSQLite3にバージョンを上げるプログラムを作るときに戸惑ったのでメモ。ライブラリとか使うのめんどいのでexeの標準入出力ストリームをリダイレクトして対応しようという魂胆。

まず、公式サイトにSQLite2のリンクがなくてはまった。Googleで検索していると、ファイルは生きてるらしくPHP と SQlite2 | itFun.jpに直リンがあって、ここからダウンロードできました。

つぎにはまったのが文字コード。標準出力のリダイレクトはProcessStartInfo.RedirectStandardOutputをtrueにしてProcess.Startに渡すとProcessのインスタンスのStandardOutputプロパティから標準出力を取得できて、ProcessStartInfo.RedirectStandardInputをtrueにするとStandardInputにアプリの標準入力へ書き込むことができる。それぞれStreamReaderとStreamWriter

StandardOutputにはStandardOutputEncodingに文字コードを指定できたけど、StandardInputにはこれに当たるプロパティがない。仕方がないのでStandardInput.BaseStreamを元に新しくStreamWriterを作った。

最終的なプログラムは以下のような形に。

/// <summary>
/// SQLite3のバージョンを変換して転送
/// </summary>
/// <param name="fromFile">バージョンアップ元のファイル</param>
/// <param name="toFile">バージョンアップ後のファイル</param>
void VersionUpSQLite(string fromFile, string toFile)
{
    // パラメータ設定
    ProcessStartInfo sqlite2StartInfo = new ProcessStartInfo(m_sqlite2Command,string.Format("\"{0}\" .dump", fromFile));
    sqlite2StartInfo.UseShellExecute = false;
    sqlite2StartInfo.RedirectStandardOutput = true;
    sqlite2StartInfo.CreateNoWindow = true;
    sqlite2StartInfo.StandardOutputEncoding = Encoding.GetEncoding("Shift_JIS"); // SJIS
    ProcessStartInfo sqlite3StartInfo = new ProcessStartInfo(m_sqlite3Command, string.Format("\"{0}\"", toFile));
    sqlite3StartInfo.UseShellExecute = false;
    sqlite3StartInfo.RedirectStandardInput = true;
    sqlite3StartInfo.CreateNoWindow = true;

    // プロセス起動
    Process sqlite2Process = Process.Start(sqlite2StartInfo);
    Process sqlite3Process = Process.Start(sqlite3StartInfo);

    // エンコーディング指定してStreamWriterを作り直す
    using (StreamWriter sqlite3Writer = new StreamWriter(sqlite3Process.StandardInput.BaseStream, new UTF8Encoding(false)))
    {
        // 全部書き込む
        sqlite3Writer.Write(sqlite2Process.StandardOutput.ReadToEnd());
    }
}