あるフォルダのなかにあるファイルをすべて取得するのであれば
1 |
string[] files = System.IO.Directory.GetFiles(@"C:\XXX", "*", System.IO.SearchOption.AllDirectories); |
これで取得できます。ところがフォルダのなかのファイルを調べようとするとアクセス拒否される場合があります。この場合は例外が発生して処理が止まってしまいます。これではファイルやフォルダのリストを取得することができません。そんなときはどうすればよいのでしょうか?
このようなときは Directory.GetFilesメソッドの第3引数を SearchOption.AllDirectories にはしないで、SearchOption.TopDirectoryOnlyとして、再帰呼び出しをするしかないのではないでしょうか?
アクセス拒否の例外が発生したらそのフォルダは飛ばして、取得できるものだけ取得します。
以下のメソッドではアクセス拒否などの例外が発生した場合はそのフォルダのパスも記録しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public void GetAllFiles(string folder, string searchPattern, List<string> filePaths, List<string> AccessDeniedFolder) { //folderにあるファイルを取得する string[] fs = Directory.GetFiles(folder, searchPattern, SearchOption.TopDirectoryOnly); // リストに追加する filePaths.AddRange(fs); //folderのサブフォルダを取得する string[] subFolders = Directory.GetDirectories(folder); //サブフォルダにあるファイルも調べる foreach(string path in subFolders) { try { GetAllFiles(path, searchPattern, filePaths, AccessDeniedFolder); } catch(Exception ex) { // アクセスを拒否された場合 AccessDeniedFolder.Add(path); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public void GetAllFolders(string folder, string searchPattern, List<string> folderPaths, List<string> AccessDeniedFolder) { //folderのサブフォルダを取得する string[] subFolders = Directory.GetDirectories(folder); folderPaths.AddRange(subFolders); //サブフォルダにあるフォルダも調べる foreach(string path in subFolders) { try { GetAllFolders(path, searchPattern, folderPaths, AccessDeniedFolder); } catch(Exception ex) { // アクセスを拒否された場合 AccessDeniedFolder.Add(path); } } } |
エクスプローラーを使えばそのフォルダのなかにあるファイルを名前順、更新日時順、ファイルのサイズ順に並べ替えることができます。そのフォルダだけでなくそのフォルダ内のフォルダも調査対象としてファイルを名前順、更新日時順、ファイルのサイズ順に並べ替えるアプリケーションをつくってみると面白いかもしれません。
C:\Program Files\Mozilla Firefoxフォルダのファイルをファイルサイズが大きい順に並べています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { FolderBrowserDialog dialog = new FolderBrowserDialog(); if(dialog.ShowDialog() == DialogResult.OK) { List<string> filePaths = new List<string>(); List<string> AccessDeniedFolder = new List<string>(); string folderPath = dialog.SelectedPath; Task.Run(()=> { GetAllFiles(folderPath, "*", filePaths, AccessDeniedFolder); string str = CreateReport(filePaths, AccessDeniedFolder); MessageBox.Show("レポートができました。保存先を指定してください。", "", MessageBoxButtons.OK, MessageBoxIcon.Information); Invoke((Action)(() => { bool ret = SaveReport(str); if(ret) MessageBox.Show("ファイルを保存しました"); else MessageBox.Show("キャンセルされました"); })); }); } } string CreateReport(List<string> filePaths, List<string> AccessDeniedFolder) { StringBuilder sb = new StringBuilder(); sb.Append("ファイルパス,作成日時,更新日時,ファイルサイズ\n"); foreach(string path in filePaths) { FileInfo info = new FileInfo(path); long size = info.Length; DateTime dtLast = info.LastWriteTime; DateTime dtCreate = info.CreationTime; string str = String.Format("{0}, {1}, {2}, {3}\n", path, dtCreate.ToString("yyyy年 MM月 dd日 HH時 mm分 ss秒"), dtLast.ToString("yyyy年 MM月 dd日 HH時 mm分 ss秒"), size ); sb.Append(str); } foreach(string path in AccessDeniedFolder) { FileInfo info = new FileInfo(path); DateTime dtLast = info.LastWriteTime; DateTime dtCreate = info.CreationTime; string str = String.Format("{0}, {1}, {2}, {3}, {4}\n", path, dtCreate.ToString("yyyy年 MM月 dd日 HH時 mm分 ss秒"), dtLast.ToString("yyyy年 MM月 dd日 HH時 mm分 ss秒"), "", "アクセス拒否" ); sb.Append(str); } return sb.ToString(); } bool SaveReport(string str) { SaveFileDialog dlg = new SaveFileDialog(); dlg.Title = "ファイルとして保存する"; dlg.Filter = "csvファイル|*.csv"; if(dlg.ShowDialog() == DialogResult.OK) { StreamWriter sw = new StreamWriter(dlg.FileName, false, Encoding.UTF8); sw.Write(str); sw.Close(); return true; } return false; } } |