【C#】指定したフォルダ配下でtxtファイルを探す方法
はじめに
新人さんのプログラミング指導で、課題を出してもただサンプルをコピペしてくるだけということはよくあると思います。
その段階から一歩先へはどう教育したらいいのかという問題をちらほら耳にするので、
自分がしてもらった教育の中でよかったと思う題材について書きます。
題材
下記の動作をするコンソールアプリの作成。
指定したフォルダの中にtxtファイルがあるかを確認する。
サブディレクトリがある場合は最下層まで確認する。
txtファイルが存在する場合はそのファイル名と作成日をJSON形式で出力する。
【実行結果イメージ】
1回目に作ったもの
SearchOption.AllDirectoriesを使用する方法。
SearchOption.AllDirectoriesを利用すれば、現在のディレクトリとすべてのサブディレクトリを検索してくれます。
SearchOption 列挙型 (System.IO) | Microsoft Docs
これを使うとコードもシンプルで簡単になります。
抜粋
// SearchOption.AllDirectoriesを利用する方法
string[] names = Directory.GetFiles(args[0], "*.txt", SearchOption.AllDirectories);
if (names[0] != null)
{
foreach (string subnames in names)
{
var date = new FileInfo(subnames);
// JSON化前にリスト化する
List<Items> texts = new List<Items>
{
new Items{ file = subnames , create_time = date.CreationTime.ToString()}
};
//JSON化
string json = JsonSerializer.Serialize(texts);
//コンソール出力
Console.WriteLine(json);
}
}
全文
上記に対してもらったフィードバック
「上記の課題の成果からわかるのは、私が目的(やりたいこと)のための調べ物ができるということ。調べた内容を実装することができるということ。
ここまでではプログラミングとしての能力が鍛えられているとは言えないです。
できるだけ、SearchOptionのようなものは使わないで、ロジックを考えてください。」
これは私自身ずっと疑問だった指摘でした。
わからないことがあっても、大抵のことは調べればすぐに答えが得られます。
業務上はそれで十分な場合も多いと思います。
しかし、コードをコピペして使えるようにすることが「プログラミングをしている」ということなのか、このままの勉強方法で果たして業務で実装できるプログラマーになれるのか。
2回目に作ったもの
SearchOption.AllDirectoriesを使用しない方法。
いわゆる再帰処理です。
私はSearchOption.AllDirectoriesを使用しない方法を考え始めてから、再帰処理という言葉に行きつくまで時間がかかりました。
初めは探索アルゴリズムの考え方を調べたりしてました。
いまいちしっくりこなくて、求める挙動を整理するところから思考しました。
ひとつ目のディレクトリの中を検索し、txtファイル探す。
ディレクトリがあれば、その中に入りまたtxtファイルを探す…
ここで繰り返しが使えそうだ、その繰り返しはまとめられそうだ、回数の制限がわからないからどうしようか…みたいな考えを文字に起こしたり図に描いてみたりしました。
試行錯誤を繰り返した結果、再帰という言葉にたどり着きました。
抜粋
static void scan(string dir)
{
string[] subdirs = Directory.GetFiles(dir, "*.txt");//dirの中のtxtを探す
try
{
foreach (string files in subdirs)
{
//作成日を取得するための処理
var date = new FileInfo(files);
//取得した情報をAddItemに渡す
Texts txts = new Texts();
txts.AddItem(files, date.CreationTime.ToString());
// JSON化前にリスト化する
List texts = new List
{
new Items{ file = files , create_time = date.CreationTime.ToString()}
};
//JSON化
string json = JsonSerializer.Serialize(texts);
Console.WriteLine(json);
}
//ファイルを探し終わったらディレクトリを探して、filesに入れる。はじめのscan(args[0]);と同じ処理ルートになる
foreach (string files in Directory.GetDirectories(dir))
{
scan(files);
}
}
catch
{
Console.WriteLine("探索中にエラーが発生しました。");
}
}
全体
2回目に作ったものも、結果的には調べたことの実装に変わりないのですが、
コピペコーディングから脱する考え方の一端がつかめたような気がしました。
おわりに
ありがたいことに、世の中には便利な技術や情報が溢れています。
車輪の再発明のようなことは業務では求められないと思いますが、自分が納得して学習していく上では必要なことでもあるのかなと思います。
世の情報の恩恵にあずかりながらも、ちゃんと自分で思考する力を付けて、人並みのコーディング、プログラミングができるようになりたいです。