【Java】FilenameFilterやFileFilterでファイル一覧にフィルタをかける!
ファイル一覧にフィルタをかけるにはFilenameFilterインターフェースやFileFilterインターフェースを使用します。
FilenameFilterは、ファイル名にフィルタリングするインターフェースであり、FileFilterは、ファイル属性を含めてフィルタリングするインターフェースです。
インターフェースとはクラスの振る舞いを定義したものです。
初めに処理内容を具体的に書かず、後からメソッドの実装をして使用するために使います。
後からメソッドの実装をするため、処理を変えたい場合に有効です。
今回はFilenameFilterとFileFilterを使ってファイル一覧にフィルタをかけます。
また、Java7から使用できるようになったDirectoryStream.Filterインタフェースを使って、独自で設定したフィルタリングの内容を実装してフィルタをかける方法やFilesクラスのnewDirectoryStreamメソッドを使用することで、パス名のパターンマッチでフィルタをかける方法についても紹介していきます。
目次
FilenameFilterとは
FilenameFilterとは、ファイル名にフィルタリングするインターフェースになります。
FilenameFilterの書き方
FilenameFilterの構文は下記となります。
1 2 3 4 5 6 7 8 9 |
import java.io.FilenameFilter; public class インターフェイス名 implements FilenameFilter { @Override public boolean accept(File Fileのインスタンス, String ファイル名かディレクトリ名) { // 処理内容 } } |
まず、FilenameFilterのインターフェースが使用できるようにFilenameFilterをインポートします。
そして、acceptメソッドのパラメータにFileのインスタンスと対象パスのファイル名かディレクトリ名を指定することでファイル名によるフィルタリングができます。
FileFilterとは
FileFilterとは、ファイル属性を含めてフィルタリングするインターフェースになります。
FileFilterの書き方
FileFilterの構文は下記となります。
1 2 3 4 5 6 7 8 9 |
import java.io.FileFilter; public class インターフェイス名 implements FileFilter { @Override public boolean accept(File Fileのインスタンス) { } } |
まず、FileFilterのインターフェイスが使用できるようにFileFilterをインポートします。
そして、acceptメソッドのパラメータにFileのインスタンスを指定することでファイルの属性などを含めてフィルタリングができます。
ファイル一覧にフィルタをかけるサンプルコード
ファイル一覧にフィルタをかけるサンプルコードを紹介します。
FilenameFiler1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//「FilenameFilter」インターフェースを実装してフィルタを行う import java.io.File; import java.io.FilenameFilter; public class FilenameFiler1 implements FilenameFilter { // 「FilenameFilter.accept」メソッドをオーバーライド @Override public boolean accept(File dir, String name) { // フィルタリング // ファイル名が「File」から始まればOK return name.startsWith("File"); } } |
FileFilter1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//「FileFilter」インターフェースを実装してフィルタを行う import java.io.File; import java.io.FileFilter; public class FileFilter2 implements FileFilter { // 「FileFilter.accept」メソッドをオーバーライド @Override public boolean accept(File path) { // フィルタリングの内容を実装 // ディレクトリであればOK return path.isDirectory(); } } |
Main.javaを実行するディレクトリ構成は下記のようになります。
C:¥study
|ーーFileA.txt
|ーーFileB.txt
|ーーFileC.txt
|ーーFileD.txt
|ーーFileD_1.txt
|ーーFileD_2.txt
Main.java
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 |
// ファイル一覧を取得する import java.io.File; public class Main { public static void main(String[] args) throws Exception { //ファイル一覧を取得するディレクトリ File target = new File("c:/study"); //「FilenameFilter」でフィルタを行ってファイル一覧を取得する File[] fileA = target.listFiles(new FilenameFilter1()); // 取得したファイル一覧を表示する System.out.println("FilenameFilterでフィルタ"); for (File file : fileA) { System.out.println(file); } // 「FileFilter」でフィルタを行ってファイル一覧を取得する File[] fileB = target.listFiles(new FileFilter1()); // 取得したファイル一覧を表示する System.out.println("FileFilterでフィルタ"); for (File file : fileB) { System.out.println(file); } } } |
出力結果
FilenameFilterでフィルタ
c:\study\FileA.txt
c:\study\FileB.txt
FileFilterでフィルタ
c:\study\FileD
FilenameFilterとFileFilterによってディレクトリにフィルタがかかっています。
今回のポイント
FilenameFilterやFileFilterでファイルにフィルタをかける
ファイル一覧にフィルタをかけるには「FilenameFilter」や「FileFilter」インタフェースを実装したクラスを使用する
● ファイル一覧を取得するFileクラスのlistFilesメソッドのパラメータに「FilenameFilter」インスタンスを指定するとファイル名にフィルタをかけることができ、「FileFilter」インスタンスを指定すると、ファイル一覧にフィルタをかけることができる
● FilenameFilterインタフェースとFileFilterインタフェースでフィルタリングを行うにはacceptメソッドを実装する必要がある
● FilenameFilterインタフェースのaccept(File, String)メソッドの第1パラメータは判定対象パスの親ディレクトリの「File」インスタンス、第2パラメータは判定対象パスのファイル名(判定対象がディレクトリの場合は最後のディレクトリ名)
● FileFilterインタフェースのaccept(File)メソッドの第1パラメータはフィルタをかけるファイルの「File」インスタンス
補足
NIO.2のFilesクラスを使用してディレクトリを作成する
NIO.2のFilesクラスを使用してディレクトリを作成するには「DirectoryStream.Filter」インタフェースやFilesクラスのnewDirectoryStreamメソッドを使用します。
NIO.2とはJava7で導入された「java.nio.file」パッケージとそのサブパッケージとを合わせたものであり、NIO.2を使用することでとても簡単にファイル処理を行うことができます。
「DirectoryStream.Filter」インタフェースを使用すると、独自で設定したフィルタリングの内容でフィルタをかけることができます。
また、FilesクラスのnewDirectoryStreamメソッドを使用することで、パス名のパターンマッチでフィルタをかけることができます。
しかし、DirectoryStreamメソッドをWindows系の環境で使用した場合は、アルファベットの大文字・小文字は区別されませんので注意してください。
DSFilter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// DirectoryStream.Filteインタフェースを実装してフィルタを行う import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Path; public class DSFilter implements DirectoryStream.Filter<Path> { //DirectoryStream.Filter.accept」メソッドをオーバーライド @Override public boolean accept(Path entryPass) throws IOException { // フィルタリング // ファイル名が「File」から始まればOK return entryPass.getFileName().toString().startsWith("File"); } } |
Sub.java
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 |
// ディレクトリ内のファイル一覧を取得する import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Sub { public static void main(String[] args) throws Exception { // ファイル一覧を取得するディレクトリ Path path = Paths.get("c:/study"); //DirectoryStream.Filterでフィルタを行ってファイル一覧を取得する try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, new DSFilter()) { // 取得したファイル一覧を表示する System.out.println("DirectoryStream.Filterでフィルタ"); for (Path file: stream) { System.out.println(file.getFileName()); } } // FilesクラスのnewDirectoryStreamメソッドでフィルタリングの内容を指定し、 // ファイル一覧を取得する System.out.println("Files.newDirectoryStreamでフィルタ"); try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, "File*")) { // 取得したファイル一覧を表示する for (Path file: stream) { System.out.println(file.getFileName()); } } } } |
出力結果
DirectoryStream.Filterでフィルタ
FileA.txt
FileB.txt
Files.newDirectoryStreamでフィルタ
FileA.txt
FileB.txt
DirectoryStream.FilterインターフェースやnewDirectoryStreamメソッドによってファイルにフィルタがかかっています。
日本語ファイル名でフィルタをかける際の注意点
ファイル名が「だ」で始まるものを抽出しようとしたとき、FilenameFilterインターフェースのacceptメソッドは、次のようになります。
1 2 3 4 |
@Override public boolean accept(File dir, String Filename) { return Filename.startsWith("だ"); } |
Windows系やLinuxの場合はこれで問題ありませんが、Mac OS Xの場合は注意してください。
Mac OS Xでは、ファイル名の「だ」という文字を「た」と「”」の2文字で管理しているため、うまく抽出することができません。
逆に「Filename.startsWith(“た”)」で判定した場合、「た」で始まるファイルと「だ」で始まるファイルを抽出することになります。
「た」を「だ」のように1文字で合成して表す方法を「NFC」といい、「た」+「”」のように2文字を結合して表す方法を「NFD」といいます。
そのため、Mac OS Xで正しくフィルタをかけるには、ファイル名を一度、NFCに正規化しましょう。
また、ひらがなやカタカナ以外にも、アルファベットのアクセント記号もNFCとして扱われます。
1 2 3 4 5 |
@Override public boolean accept(File dir, String name) { String normal = Normalizer.normal(name, Normalizer.Form.NFC); return normal.startsWith("た"); } |
関連記事
ディレクトリ内のファイル一覧を取得する方法についてはこちらをご参考ください。
ST
株式会社flyhawkのSTです。フライテックメディア事業部でのメディア運営・ライター業務なども担当。愛機はMac Book AirとThinkPad。好きな言語:swift、JS系(Node.js等)。好きなサーバー:AWS。受託開発やプログラミングスクールの運営をしております。ご気軽にお問い合わせください。