RSS

Advent LINQ (3): FilesAsEnumerable

03 12月

Directory.GetFilesが配列を返すので、列挙子にしてみる。特にSearchOption.AllDirectoriesが指定されると、処理が返って来るまでにかなり時間がかかることがある。
フォルダーは再帰探索する必要があるので、実装は少し捻る必要がある。

public static class LinqExtensions
{
	public static IEnumerable<string> FilesAsEnumerable(string path, string patterns)
	{
		foreach (var directoryPath in
			Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly))
		{
			foreach (var filePath in
				FilesAsEnumerable(directoryPath, patterns))
			{
				yield return filePath;
			}
		}

		foreach (var filePath in
			Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly))
		{
			yield return filePath;
		}
	}
}

これでもいいのだが、foreachだらけで見通しが悪い。全てクエリに置き換える。

public static class LinqExtensions
{
	public static IEnumerable<string> FilesAsEnumerable(string path, string patterns)
	{
		var byDirectory =
			from directoryPath in Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly)
			from filePath in FilesAsEnumerable(directoryPath, patterns)
			select filePath;

		var byFile =
			from filePath in Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly)
			select filePath;

		return byDirectory.Concat(byFile);
	}
}

これでファイルの列挙は以下のように記述できる。

foreach (var path in LinqExtensions.FilesAsEnumerable(@"C:\project", "*.cs"))
{
	Console.WriteLine(path);
}

ファイルの逐次探索が可能になったので、大量のファイルをパイプライン処理できるようになった。
なお、このコードは.NET 4.0以降では、Directory.EnumerateFilesとほぼ同じ動作となる。

広告
 
コメントする

投稿者: : 2013/12/03 投稿先 .NET, LINQ

 

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。