ディレクトリとは、ファイルや他のディレクトリを含む組織的なファイルシステム構造です。Javaでは、使用しているバージョンに応じて、ディレクトリ内を移動する方法がいくつか用意されています。以下に例を挙げます。
- FileクラスのlistFiles()メソッドを使用する
- Java 7以降でのDirectoryStreamの使用
- Java 8以降で静的Files.list()メソッドを使用する
- Java 8以降でwalk()メソッドを使用する
このプログラミング チュートリアルでは、上記の各テクニックを利用して Java でディレクトリ構造をナビゲートする方法を説明します。
参照:トップ Java IDE
JavaのFile listFiles()メソッド
listFiles()はjava.io.Fileクラスのインスタンスメソッドです。これを使用するには、コンストラクタにパスを指定して新しいFileオブジェクトをインスタンス化し、そのオブジェクトに対してlistFiles()を呼び出すだけです。listFiles ()はFileオブジェクトの配列を返します。プログラマーはこれを反復処理することで、個々のファイルに関する詳細情報を取得したり、ファイルに対して操作を実行したりできます。以下は、Windows の「C:\My Documents」フォルダ内のすべてのファイルとディレクトリを一覧表示する基本的な例です。
package com.developer; import java.io.File; public class ListFilesExample { public static void main(String[] args) { // ファイルとディレクトリの名前を // Files の配列に格納します。 // バックスラッシュ文字をエスケープすることを忘れないでください。 File[] files = new File("C:\\My Documents").listFiles(); // ファイル配列を走査します for (File file : files) { // サブディレクトリが見つかった場合は、 // サブディレクトリの名前を出力します if (file.isDirectory()) { System.out.println("Directory: " + file.getName()); } else { // ファイル名を出力します System.out.println("File: " + file.getName()); } } } }
見つかったディレクトリとファイルの一部を以下に示します。
ディレクトリ: AAMS ディレクトリ: Addictive Drums ディレクトリ: Angular ディレクトリ: angular-starter ディレクトリ: Any Video Converter ディレクトリ: 記事 ファイル: アバター - House Of Eternal Hunt - transposed.tg ファイル: アバター - House Of Eternal Hunt.tg ファイル: アバター - 王の伝説.tg ディレクトリ: bgfx
Javaでの再帰ディレクトリトラバーサル
ディレクトリをテストできるため、次の Java コード例に示すように、for ループを別のメソッドに移動して、メソッドに提供されたファイルだけでなくサブディレクトリのファイルをリストするために再帰的に呼び出すことができます。
package com.developer; import java.io.File; public class RecursiveListFilesExample { public static void main(String[] args) { listFilesInDirectory(new File("C:\\My Documents")); } private static void listFilesInDirectory(File dirPath) { File filesList[] = dirPath.listFiles(); // ファイル配列を走査します for (File file : filesList) { // サブディレクトリが見つかった場合は、 // サブディレクトリの名前を出力します if (file.isDirectory()) { System.out.println("Directory: " + file.getName()); listFilesInDirectory(file); } else { // 指定されたパスにあるファイル名を出力します System.out.println("File: " + file.getName()); } } } }
プログラムの出力を見ると、サブディレクトリのファイルもリストされていることがわかります。
ディレクトリ: AAMS ファイル: AAMS V3 マニュアル.pdf ファイル: AAMS V4 セットアップ.exe ファイル: AAMS.xml ファイル: License.txt ファイル: Version.txt ディレクトリ: Addictive Drums ディレクトリ: 設定 ファイル: MidifileDatabaseCache.dat ファイル: Recent.dat
参照: Javaを学ぶためのトップオンラインJavaコース
DirectoryStream を使用して Java でファイルをループする
Java 7では、 listFiles()の代替としてDirectoryStreamが導入されました。これは for-each 構文と相性が良く、ディレクトリの内容を一度にすべて読み取るのではなく、反復処理することができます。
以下のサンプル コードは、ディレクトリのファイルを一覧表示するメソッドでJava のDirectoryStreamを使用する方法を示しています。
public Set<String> listFilesUsingDirectoryStream(String dir) throws IOException { Set<String> fileSet = new HashSet<>(); try (DirectoryStream<Path> stream = Files.newDirectoryStream( Paths.get(dir))) { for (Path path : stream) { if (!Files.isDirectory(path)) { fileSet.add(path.getFileName() .toString()); } } } return fileSet; }
上記では、Javaにtry-with-resources構文を使ってDirectoryStreamリソースのクローズ処理を任せています。静的Files.isDirectory(path)メソッドを使ってディレクトリを除外し、フォルダ内のファイルのSetを返すことができます。
静的 Files.list() メソッドの使用
Java 8では、 java.nio.file.Filesに新しいlist()メソッドが導入されました。この list メソッドは、ディレクトリ内のエントリを遅延読み込みしたStreamを返します。そのため、大きなフォルダの処理がより効率的になります。ファイル名のSetを返すメソッドを以下に示します。
public Set<String> listFilesUsingFilesList(String dir) throws IOException { try (Stream<Path> stream = Files.list(Paths.get(dir))) { return stream .filter(file -> !Files.isDirectory(file)) .map(Path::getFileName) .map(Path::toString) .collect(Collectors.toSet()); } }
上記のコードはlistFiles()と似ているように見えますが、開発者が各ファイルのパスを取得する方法が異なります。
ここでも、ストリームを読み取った後にディレクトリ リソースが閉じられるように、try-with-resources構造を使用してストリームを作成しました。
Javaでディレクトリの内容を走査する方法
walk()メソッドは、指定された開始ファイル/ディレクトリから深さ優先(つまり、最も深いファイル/ディレクトリから開始)でファイルツリーを走査し、Streamを返します。次のプログラムは、「C:\My Documents」以下のファイルツリー全体の完全なファイルパスを出力します。
java.io.IOException をインポートします。 java.nio.file.Files をインポートします。 java.nio.file.Path をインポートします。 java.nio.file.Paths をインポートします。 import java.util.stream.Stream; class FilesWalkExample { public static void main(String[] args) throws IOException { // try-catch ブロックを作成し、 // ローカル マシンのディレクトリ パスを提供します try (Stream<Path> filepath = Files.walk(Paths.get("C:\\My Documents"))) { // ディレクトリとファイルのパス全体を出力します filepath.forEach(System.out::println); } // ディレクトリが存在しない場合は例外をスローします catch (IOException e) { throw new IOException("Directory not found!"); } } }
出力の最初の数行は、ファイルのトラバーサルが最も深いところから始まったことを確認します。
I:\My Documents\Angular\my-app\node_modules\selenium-webdriver\ lib\test\data\proxy I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\proxy\page1.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\proxy\page2.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\proxy\page3.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\readOnlyPage. html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\rectangles.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\Redirect.aspx I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\Redirect.aspx.cs I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\resultPage.html
Files::isRegularFileフィルター条件を削除することで、ディレクトリも含めることができます。
Javaにおけるディレクトリナビゲーションに関する最終的な考察
Javaでは、使用しているバージョンに応じて、ディレクトリをトラバースする方法がいくつか用意されています。主な方法を紹介しましたが、Java 8でStream APIが導入されて以降、Javaではディレクトリを移動する方法が他にもあります。
参照: Maven ビルド自動化ツールのレビュー