Home>C# Tips>

ディレクトリ走査

更新日:2003/08/10

System.IO.DirectoryInfoを使用すると簡単にディレクトリ走査が出来ます。スクリプト言語の手軽さには敵わないですが、それでも結構楽です。


クラス構成

DirectoryScanner
指定したディレクトリを走査します。正規表現を使ったパターンマッチにも対応。
MyApp
DirectoryScannerクラスの使用例。

dirscan.cs

using System;
using System.IO;
using System.Text.RegularExpressions;

namespace Mei
{
  /// <summary>
  ///  ファイル発見イベントを処理するメソッドを表します。
  /// </summary>
  public delegate void FileFoundEventHandler(FileInfo fi);
  /// <summary>
  /// ディレクトリ発見イベントを処理するメソッドを表します。
  /// </summary>
  public delegate void DirectoryFoundEventHandler(DirectoryInfo di);

  /// <summary>
  /// ディレクトリ走査を行うクラス。
  /// </summary>
  public class DirectoryScanner {
    private Regex regex;
    private bool scanSubDir;
    /// <summary>
    /// ファイル発見イベント。
    /// </summary>
    public event FileFoundEventHandler FileFound;
    /// <summary>
    /// ディレクトリ発見イベント。
    /// </summary>
    public event DirectoryFoundEventHandler DirectoryFound;

    /// <summary>
    /// コンストラクタ。
    /// </summary>
    public DirectoryScanner() : this(true) {
    }

    /// <summary>
    /// コンストラクタ。
    /// </summary>
    /// <param name="scanSubDir">サブディレクトリを対象にするかを指定します。</param>
    public DirectoryScanner(bool scanSubDir) {
      this.scanSubDir =scanSubDir;
    }

    /// <summary>
    /// 指定したディレクトリを走査する。
    /// </summary>
    /// <param name="path">走査対象となるディレクトリ。</param>
    /// <exception cref="System.IO.DirectoryNotFoundException">指定したディレクトリが存在しなかった場合、例外が発生する。</exception>
    public void Scan(string path) {
      regex = null;
      ExecuteScan(path);
    }

    /// <summary>
    /// 指定したディレクトリを走査し、パターンにマッチするファイルを探す。
    /// </summary>
    /// <param name="path">検索対象となるディレクトリ。</param>
    /// <param name="pattern">マッチングする正規表現文字列。</param>
    /// <exception cref="System.IO.DirectoryNotFoundException">指定したディレクトリが存在しなかった場合、例外が発生する。</exception>
    public void Scan(string path, string pattern) {
      regex = new Regex(pattern);
      ExecuteScan(path);
    }

    /// <summary>
    /// ファイルがマッチするかどうかを判断する。
    /// </summary>
    /// <param name="name">ファイル名。</param>
    /// <returns>マッチする場合はtrueを返す。</returns>
    private bool IsMatch(string name) {
      return regex == null || regex.IsMatch(name);
    }

    /// <summary>
    /// ディレクトリ走査を行う。
    /// </summary>
    /// <param name="path">走査対象となるディレクトリ。</param>
    private void ExecuteScan(string path) {
      DirectoryInfo di = new DirectoryInfo(path);
      foreach (FileSystemInfo fsi in di.GetFileSystemInfos()) {
        if (IsMatch(fsi.Name)) {
          if (fsi is DirectoryInfo) {
            if (DirectoryFound != null) {
              // イベントの発火
              DirectoryFound(fsi as DirectoryInfo);
            }
          }
          else {
            if (FileFound != null) {
              // イベントの発火
              FileFound(fsi as FileInfo);
            }
          }
        }

        if (scanSubDir && fsi is DirectoryInfo)
          ExecuteScan(fsi.FullName);
      }
    }    
  }
}

myapp.cs

using System;
using System.IO;
using System.Reflection;
using Mei;

/// <summary>
///  DirectoryScannerテストサンプル
/// </summary>
class MyApp {
  private static int fileCount;
  private static int dirCount;

  static MyApp() {
	fileCount = 0;
	dirCount = 0;
  }

  static void NotifyFileFound(FileInfo fi) {
	fileCount++;
	Console.WriteLine("[File] {0}", fi.FullName);
  }

  static void NotifyDirectoryFound(DirectoryInfo di) {
	dirCount++;
	Console.WriteLine("[Dir] {0}", di.Name);
  }

  [STAThread]
  static void Main(string[] args)
  {
	if (args.Length == 0) {
	  Console.WriteLine("usage : {0} serch_dir [pattern]", 
		Assembly.GetEntryAssembly().GetName().Name);
	  return;
	}

	DirectoryScanner ds = new DirectoryScanner(true);
	ds.FileFound += new FileFoundEventHandler(NotifyFileFound);
	ds.DirectoryFound += new DirectoryFoundEventHandler(NotifyDirectoryFound);
	try {
	  if (args.Length == 1)
		ds.Scan(args[0]);
	  else
		ds.Scan(args[0], args[1]);
	}
	catch (DirectoryNotFoundException e) {
	  Console.WriteLine(e.Message);
	}
	Console.WriteLine("File={0}, Dir={1} found.", fileCount, dirCount);
  }
}

Home>C# Tips>