前回再帰的なメソッドの呼び出しを利用してディレクトリの階層のどこかにあるファイルを選択するメソッドを作成しました。ただまだ欲しい機能が二つあります。一つは上の階層へ移動するオプションの追加です。下のディレクトリには進めますがやっぱり上に戻りたいと思った時に戻れないのは不便です。もう一つはキャンセルです。目当てのファイルが見つからないとか、そもそもこのまま処理を進めて欲しくない、といった場合に選択をせずに終わるオプションをつけたいと思います。
実装の方法
選択肢を連想配列につけます。現在のディレクトリの親ディレクトリを取得するには
File parent = dir.getParentFile();
のように取得します。選択肢には単に「上のディレクトリへ」と表示します。選択肢のコードはUPを意味するuとします。
キャンセルの場合はファイルの指定がないのでnullを使います。Fileの連想配列の方には何もputしません。存在しない鍵で検索してもnullしか帰らないからです。選択肢のコードはQUITのqにします。
キャンセルした時にはnullが変えるためディレクトリの判定はnullでないことを確認してから行うようにします。
if(file != null && file.isDirectory()){ return readFile(file); }
実装する
追加する処理が決まったら実装をします。
public File readFile(File dir) { FilenameFilter filter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { if (name.toLowerCase().equals(".ds_store")) { return false; } return true; } }; File[] files = dir.listFiles(filter); LinkedHashMap<String, String> str_map = new LinkedHashMap<>(); LinkedHashMap<String, File> file_map = new LinkedHashMap<>(); // 親ディレクトリを追加する File parent = dir.getParentFile(); if(parent != null){ str_map.put("u", "上のディレクトリへ"); file_map.put("u", parent); } str_map.put("q", "キャンセル"); for (int i = 0;i < files.length;i++) { String sign; if (files[i].isFile()) { sign = "[f]"; } else if (files[i].isDirectory()) { sign = "[d]"; } else { sign = "[?]"; } str_map.put(Integer.toString(i), sign + " " + files[i].getName()); file_map.put(Integer.toString(i), files[i]); } String key = readKey(dir.getAbsolutePath(), "ファイルを選んでください", str_map); File file = file_map.get(key); if(file != null && file.isDirectory()){ return readFile(file); } return file; }
だんだん複雑になってきました。まだ大丈夫ですがもっと複雑になるようだったら機能を考え分割をしても良いかもしれません。
呼び出し側は以前と同じですがキャンセル時にはnullで戻る可能性があるため分岐を作っておきます。
TerminalUtil util = new TerminalUtil(); File file = util.readFile(new File("/Users/myaccount/mywork")); if(file == null){ System.out.println("キャンセルしました。"); }else{ System.out.println("選ばれたファイルは" + file.getAbsolutePath() + "です。"); }
実行結果です。最初はキャンセルしたところ。
[/Users/myaccount/mywork] u:上のディレクトリへ q:キャンセル 0:[d] dir_1 1:[f] file_a.txt 2:[f] file_b.txt 3:[f] file_c.txt ファイルを選んでください>q キャンセルしました。
次は一つ下のディレクトリにいってまた上に戻ってきてファイルを選択したところです。
[/Users/myaccount/mywork] u:上のディレクトリへ q:キャンセル 0:[d] dir_1 1:[f] file_a.txt 2:[f] file_b.txt 3:[f] file_c.txt ファイルを選んでください>0 [/Users/myaccount/mywork/dir_1] u:上のディレクトリへ q:キャンセル 0:[f] file_d.txt 1:[f] file_e.txt ファイルを選んでください>u [/Users/myaccount/mywork] u:上のディレクトリへ q:キャンセル 0:[d] dir_1 1:[f] file_a.txt 2:[f] file_b.txt 3:[f] file_c.txt ファイルを選んでください>1 選ばれたファイルは/Users/myaccount/mywork/file_a.txtです。