🌟
全ファイル検索を実装しました。 日記
C# コンソール駆動の全ファイル検索ソフト(開発進捗)
概要
指定したフォルダの中身をすべて取得し、ファイル名で検索するソフト。
ファイルパスのリストを取得することに多くの時間を要する。
C:/のすべてのファイルを取得するには、1分ほど待つ必要がある。
検索は、高速化をしていなくともある程度の速度が出る。
どのようにユーザが欲しいデータを判定するかのほうが大変な印象。
Cのすべてを取得した場合は、検索に引っかかるものが多すぎて使い物にならない。
文書を保存しているフォルダを指定するくらいが望ましいと思う。
仕様
mode 0 読み込みモード フォルダパスを指定 読み込みが完了すると、自動でmode 1に
mode 1 検索モード そのまま検索できる
.c コンソールクリア
.h quary 読み込み 履歴から読み込みする 例えば、c:/user/tagaha/jsjss/ppp をmode 0で読み込んだことがある場合、.h pppを入力することで、すぐに検索できるようになる。
.o id ファイルを開く
.f id フォルダを開く
履歴は、アプリケーションのフォルダの、historyに格納されます。
開発途中ではあるが、コードを載せておく。
アクセス権限のないファイルを読みに行き、エラーで止まるという問題が、
ファイル取得にはつきものだ。
解決するために多くの時間を使用したので、
参考にしてください。
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics; // OrderByDescendingを使用するために追加
public class Scanner
{
// ... GetAllFilesRecursiveメソッドは変更なし ...
private static void GetAllFilesRecursive(string path, List<string> fileList)
{
fileList.Add(path);
try
{
fileList.AddRange(Directory.GetFiles(path, "*").Where(s =>!s.EndsWith(".dll") && !s.EndsWith(".jpg" ) && !s.EndsWith(".png") && !s.EndsWith(".svg")));
}
catch (UnauthorizedAccessException) { Console.WriteLine($"[スキップ] アクセス権がありません: {path}"); }
catch (Exception ex) { Console.WriteLine($"[エラー] ファイル取得中にエラーが発生しました: {path} ({ex.Message})"); return; }
try
{
foreach (var dir in Directory.GetDirectories(path))
{
GetAllFilesRecursive(dir, fileList);
}
}
catch (UnauthorizedAccessException) { Console.WriteLine($"[スキップ] アクセス権がありません: {path}"); }
catch (Exception ex) { Console.WriteLine($"[エラー] サブディレクトリ取得中にエラーが発生しました: {path} ({ex.Message})"); }
}
/// <summary>
/// パス文字列をファイル名/フォルダ名として使用できる安全な文字列に変換します。
/// </summary>
/// <summary>
/// パス文字列をファイル名/フォルダ名として使用できる安全な文字列に変換します。
/// </summary>
private static string SanitizePath(string path)
{
string invalidChars = new string(Path.GetInvalidFileNameChars());
invalidChars += ":"; // ドライブ名(C:)のコロンも置換対象に含める
foreach (char c in invalidChars)
{
path = path.Replace(c.ToString(), "_");
}
return path;
}
public static void Main(string[] args)
{
string[] files = [];
int mode = 0;
// アプリケーションフォルダ内に履歴保存用のベースフォルダを作成
string historyBaseDir = Path.Combine(AppContext.BaseDirectory, "history");
Directory.CreateDirectory(historyBaseDir);
while (true)
{
var read_text = Console.ReadLine().Trim(); // 前後の空白を除去
if (read_text == "") {
continue;
}
if (read_text.Trim().ToLower() == ".c") {
Console.Clear();
continue;
}
var array = read_text.Split(new[] { ' ' }, 2);
if (array.Length == 2)
{
string command = array[0].Trim().ToLower();
string argument = array[1].Trim().Trim('"');
if (command == "mode")
{
mode = int.Parse(argument);
Console.WriteLine("\n\n" + "now mode " + mode);
continue;
}
if (command == ".o" || command == ".f")
{
// (o, f コマンドの処理は変更なし)
if (int.TryParse(argument, out int fileIndex) && fileIndex >= 0 && fileIndex < files.Length)
{
string filePath = files[fileIndex];
if (command == ".o" && File.Exists(filePath))
{
new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true } }.Start();
}
else if (command == ".f" )
{
string dir = "";
if (Directory.Exists(filePath)) {
dir = filePath;
}
else {
dir = Path.GetDirectoryName(filePath);
}
if (Directory.Exists(dir)) {
new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo(dir) { UseShellExecute = true } }.Start();
}
}
}
continue;
}
else if (command == ".h")
{
string targetPath = argument;
try
{
string search_path = "";
string[] names = System.IO.Directory.GetDirectories(
historyBaseDir, "*", System.IO.SearchOption.AllDirectories);
for (var i = 0;i < names.Length;i++)
{
if (names[i].IndexOf(targetPath, StringComparison.OrdinalIgnoreCase) >= 0) {
search_path = names[i];
break;
}
Console.WriteLine(names[i]);
}
if (Directory.Exists(search_path))
{
var historyFiles = Directory.GetFiles(search_path, "*.txt")
.OrderByDescending(f => new FileInfo(f).LastWriteTime)
.ToList();
if (historyFiles.Count > 0)
{
Console.WriteLine($"\n「{search_path}」の検索履歴:");
for (int i = 0; i < historyFiles.Count; i++)
{
Console.WriteLine($" [{i}] {new FileInfo(historyFiles[i]).LastWriteTime}");
}
string choiceStr = "0";
if (int.TryParse(choiceStr, out int choice) && choice >= 0 && choice < historyFiles.Count)
{
files = File.ReadAllLines(historyFiles[choice]);
mode = 1; // 検索後のモードに移行
Console.WriteLine($"\n履歴を読み込みました ({files.Length}件)。準備ができました。");
}
else
{
Console.WriteLine("無効な番号です。");
}
}
else
{
Console.WriteLine($"\n「{targetPath}」の履歴は見つかりませんでした。");
}
}
else
{
Console.WriteLine($"\n「{targetPath}」の履歴は見つかりませんでした。");
}
}
catch (Exception ex)
{
Console.WriteLine($"\n履歴の読み込み中にエラーが発生しました: {ex.Message}");
}
continue;
}
}
read_text = read_text.Trim('"');
switch (mode)
{
case 0:
if (Directory.Exists(read_text))
{
string path = read_text;
Console.WriteLine("ファイルのリストを作成しています...");
List<string> fileList = new List<string>();
GetAllFilesRecursive(path, fileList);
files = fileList.ToArray();
// ===== ここから自動保存処理 =====
try
{
// 検索パスから履歴保存用のサブフォルダ名を生成
string targetDirName = Path.GetFileName(path);
if (targetDirName.Trim() == "") {
targetDirName = path;
}
string saveDir = Path.Combine(historyBaseDir, SanitizePath(targetDirName));
Directory.CreateDirectory(saveDir);
// タイムスタンプ付きのファイル名を生成
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string savePath = Path.Combine(saveDir, $"{timestamp}.txt");
File.WriteAllLines(savePath, files);
Console.WriteLine($"\nファイル一覧の履歴を保存しました: {savePath}");
}
catch (Exception ex)
{
Console.WriteLine($"\n履歴の保存中にエラーが発生しました: {ex.Message}");
}
// ===== ここまで自動保存処理 =====
Console.WriteLine("準備ができました");
mode = 1;
}
else
{
Console.WriteLine("フォルダがありません。フォルダを右クリックからパスをコピーを選択し、張り付けてください");
}
break;
case 1:
if (read_text.Trim() == "") {
Console.WriteLine("入力が空です");
break;
}
// (case 1の検索表示処理は変更なし)
string z_path_ecoal = "";
var strList = new List<string>();
if (files.Length > 0)
{
for (int i = 0; i < files.Length; i++)
{
string file_name = Path.GetFileName(files[i]);
if (file_name.IndexOf(read_text, StringComparison.OrdinalIgnoreCase) >= 0)
{
string dir = "";
if (Directory.Exists(files[i])) {
dir = files[i];
}
else {
dir = Path.GetDirectoryName(files[i]);
}
if (dir != z_path_ecoal)
{
z_path_ecoal = dir;
strList.Add(i +" "+ dir);
Console.WriteLine($"\n{dir}\n");
}
Console.WriteLine($" {i} {file_name}");
}
}
Console.WriteLine("\n\n\n\n\n\n");
List<string> sortedAscending = strList.OrderBy(s => s.Length).ToList();
foreach (string file_name in sortedAscending) { Console.WriteLine(file_name); }
}
break;
}
}
}
}
Discussion