4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

安全にC#でファイルを検索する(サブディレクトリも)

Last updated at Posted at 2019-04-12

#安全にファイルを検索したい(サブディレクトリも)
##Directory.GetFiles()とかDirectory.EnumerateFiles()
.Net FreameworkのDirectory.GetFiles()とかDirectory.EnumerateFiles()とか、サブディレクトリも含むオプション(SearchOption.AllDirectories)をつけるとすぐに権限不足で例外を吐く使えない子なので、代替手段をいろいろ考えたりしている。要はディレクトリを全部列挙してから各ディレクトリをサブディレクトリを含まずに検索する。
ところが、ディレクトリを列挙するDirectory.GetDirectories()Directory.EnumerateDirectories()も同じ理由で使えない子なのである。

クラシカルな手法としてはtrycatchで例外をハンドリングしながら個別のディレクトリを再帰を使いながら検索していく方法。
プログラムの入門者が勉強するのにはいいのだけど、例外は重いので処理は遅くなるのだ。

##ちょっと冴えた方法
そこで、Process$“cmd /c dir {DirectoryName} /a:d /s /b”を投げて標準出力をリダイレクトしてみた。標準出力にディレクトリの列挙がベタテキストで返ってくるのだ。これはWindowsでしか使えないけど、Windows以外のOSなら$"ls -lR {DirectoryName}"でいける。
具体的にはこんな感じ。

EnumerateFilesSafer.cs
Enumerable<String> EnumerateFilesSafer(String DirectoryName)
{
  var psi = ProcessStartInfo("cmd", $"/c dir \"{DirectoryName}\" /a:-d /s /b");
  psi.UseShellExecute = false;
  psi.RedirectStandardOutput = true;
  var ps = Process(psi);
  ps.Start();
  return ps.StandardOutput.ReadToEnd().Split("¥r¥n".ToCharArray()).Where(p => p!="");
}

これが強烈に遅い。
遅いのは当たり前で、ReadToEnd()を使っているから、子プロセスが全部ディレクトリを吐くまでこの行の処理が終わらないのだ。
メソッド呼んで60秒経つとVisualStudioちゃんに怒られるので、こういうのはやめましょう。

##もうちょっと冴えた方法(yield returnを使う)
そこで、doループで回しながらyield return ps.StandardOutput.ReadLine();
で列挙を返すようにしたら、かなり速くなった。具体的にはこんな感じ。

EnumerateFilesSaferFaster.cs

Enumerable<String> EnumerateFilesSafer(String DirectoryName)
{
  var psi = ProcessStartInfo("cmd", $"/c dir \"{DirectoryName}\" /a:-d /s /b");
  psi.UseShellExecute = false;
  psi.RedirectStandardOutput = true;
  var ps = Process(psi);
  ps.Start();
  do {
    yield return ps.StandardOutput.ReadLine();
  } while (!ps.StandardOutput.EndOfStream);
}

これだと、この後の、各ディレクトリのファイル検索のための検索が呼ばれるまで次の行を読みに行かないのだ。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?