車輪の再発明

ちょっと必要になってアーカイブからビットマップやWaveファイルを引っこ抜くツールを作りました。ツール自体は大したことしてないのですがプラグイン形式にしてみたので、そこだけ紹介します。

この手のツールは各種フォーマットに対応したりするので、プログラムの中に解析ルーチンを抱え込むのは得策では無く、大抵は外部DLLを呼び出すような形を取っています。とは言ってもDLL作るのもそれなりに面倒なので、エディタでファイルをちゃちゃっと直して実行出来れば、もっと楽になります。そこで、このツールではC#のソースファイルをそのままプラグインとし、実行時にコンパイルして読み込むようにしてみました。

プログラムの構造

こんな感じになっていて、pluginディレクトリにあるファイルが実行時に読み込まれます。

プラグインの内容 (wave.cs)

using System.IO;
using System.Text;
using wabi;

// 必ずFileTypeから継承
public class FileTypeWave : FileType {
  public FileTypeWave() {
    key = Encoding.ASCII.GetBytes("RIFF");
    // 保存ファイルの拡張子
    ext = ".wav";
  }

  // ファイルタイプコンボボックの表示名
  public override string ToString() {
    return "WAVE";
  }

  // 検索ボタンを押したタイミングで呼ばれる
  // pathName : 対象ファイル
  public override void DoIt(string pathName) {
    if (Key.Length == 0)
      return;

    using (FileStream fs = File.OpenRead(pathName)) {
      int b;
      int k = 0;
      int s;
      BinaryReader br = new BinaryReader(fs);
      while ((b = fs.ReadByte() ) >= 0) {
        if (b == Key[k]) {
          if (++k == key.Length) {
            s = br.ReadInt32();
            int h = (Key.Length + 4);
            // OnFileFoundを呼ぶとリストに追加
            // 引数は順に位置、サイズ
            OnFileFound(fs.Position - h, s + h);
            fs.Seek(s, SeekOrigin.Current);
            k = 0;
          }
        }
        else {
          if (--k > 0)
            fs.Seek(-k, SeekOrigin.Current);
          k = 0;
        }
      }
    }
  }
}

必要な作業は以下の通り。

  • 拡張子の設定
  • ToStringのオーバーライド
  • DoItの実装

ほとんどの作業はDoItの中で切り出しの開始位置とそのサイズを引数にOnFileFoundを呼んであげることです。

これでテキストエディタプラグインが書けるようになりましたが、言語がC#なのでまだ敷居が高いかも知れません。作った後でVB.NETでも書けるようにすれば良かったとちょっと後悔しました。(^^;
また、折角なのでAppDomainを使ったダイナミックローディングもやろうかと考えましたが、サンプルとしてはややこしくなりすぎるので今回は見送りです。

ソースファイルはこちらに置いておきます。