文件過濾器的使用


文件過濾器的作用:在眾多的文件中,篩選出符合條件的文件.例如在我的電腦中的,D:\文檔\瀏覽器下載目錄下,篩選出所有的以.exe或者.pdf等等結尾的文件

在java中,專門提供了文件過濾器接口.

public interface FilenameFilter    accept(File dirs,String name)

public interface FileFilter       accept(File pathname);

這兩個過濾器中,實現文件過濾功能的函數正是accept,接口中也只有一個函數.

在使用時,要對過濾器接口進行實現

區別:

FilenameFilter中的accept函數接收的是兩個參數:指定父目錄的路徑和父目錄路徑中所有的子文件或者子文件夾,需要將這兩個參數封裝成File的對象再使用File中的功能

FileFilter中的accept函數接收的則直接是:完整的路徑,即需要進行過濾操作的文件或文件夾,直接可以使用File中的功能

 

要想完成過濾功能,同時還需要File類中的兩個函數:

1)public String[] list(FilenameFilter filter)  將滿足過濾器條件的以數組形式返回

2)public File[] listFiles(FilenameFilter filter)  將滿足過濾器條件的以File對象數組的形式返回

 1     public String[] list(FilenameFilter filter) {
 2         String names[] = list();
 3         if ((names == null) || (filter == null)) {
 4             return names;
 5         }
 6         List<String> v = new ArrayList<>();
 7         for (int i = 0 ; i < names.length ; i++) {
 8             if (filter.accept(this, names[i])) {
 9                 v.add(names[i]);
10             }
11         }
12         return v.toArray(new String[v.size()]);  //從源代碼中可以看到,list返回的是一個string類型的數組,而listFile返回的是File對象數組(下面可以看到)
13     }

從源代碼中可以看到,list返回的是一個String類型的數組,而listFiles返回的是File對象數組(在下面會附源代碼)

 

這兩個函數的參數也可以是(FileFilter filter),操作更為簡單

 

以FilenameFilter為例,分別使用list和listFiles()

1 public boolean accept(File dir, String name) {
2         //先判斷是否以.exe后綴結尾
3         boolean matched = name.endsWith(".exe");
4         //將dir和name封裝成一個File對象,再使用File中的功能
5         File f = new File(dir,name);
6         boolean isFile = f.isFile();
7 
8         return matched && isFile;
9     }

主函數中:

 1 public static void main(String[] args) {
 2         //創建父目錄File類的對象parent
 3         File parent = new File("D:\\文檔\\瀏覽器下載");
 4         //創建文件過濾器的對象
 5         MyFilenameFilter my = new MyFilenameFilter();
 6         method_1(parent, my);
 7 
 8     }
 9 private static void method_1(File parent, MyFilenameFilter my) {
10         //使用parent調用list.返回的是子文件或者子文件夾,下面需要封裝
11         String[] names = parent.list(my);
12         for(String name : names){
13             //System.out.println(name);
14             File file = new File(parent,name);
15             String path = file.getAbsolutePath();
16             System.out.println(file);
17             System.out.println(path);
18         }
19     }

如果使用listFile()的話,返回的直接是滿足條件的文件對象數組

 1     private static void method_2(File parent, MyFilenameFilter my) {
 2         //使用parent調用listfiles,返回的是File對象數組,下面不需要封裝
 3         File[] names = parent.listFiles(my);
 4         for(File name : names){
 5             File path = name.getAbsoluteFile();
 6             System.out.println(name);
 7             System.out.println(path);
 8         }
 9         
10     }

 

如果使用FileFilter的話

1 public boolean accept(File pathname) {
2         //pathname是一個File對象,可以直接調用File中的功能
3         boolean matched = pathname.getName().endsWith(suffix);
4         boolean isFile = pathname.isFile();
5         return matched && isFile ;
6     }
 1     public static void main(String[] args) {
 2         //創建父目錄File類的對象parent
 3         File parent = new File("D:\\文檔\\瀏覽器下載");
 4         //創建文件過濾器的對象
 5         MyFileFilter fileFilter = new MyFileFilter();
 6         method_3(parent, fileFilter);
 7 
 8     }
 9 
10     private static void method_3(File parent, MyFileFilter fileFilter) {
11         //
12         File[] names = parent.listFiles(fileFilter);
13         for(File name : names){
14             System.out.println(name);
15         }
16     }

以上便是我們要使用過濾器的話,需要實現的代碼.

那么問題又來了,accept函數到底是什么時候被調用執行的呢?這個和底層的源代碼有關.

1     public File[] listFiles(FilenameFilter filter) {
2         String ss[] = list();
3         if (ss == null) return null;
4         ArrayList<File> files = new ArrayList<>();
5         for (String s : ss)
6             if ((filter == null) || filter.accept(this, s))  //accept的主要區別在這.accept需要接收兩個參數,並由我們手動完成封裝
7                 files.add(new File(s, this));
8         return files.toArray(new File[files.size()]);
9     }
 1    public File[] listFiles(FileFilter filter) {
 2         String ss[] = list();
 3         if (ss == null) return null;
 4         ArrayList<File> files = new ArrayList<>();
 5         for (String s : ss) {
 6             File f = new File(s, this);  //底層自動幫我們對s和this進行了封裝,最后accept只需要接收一個File對象就可以了
 7             if ((filter == null) || filter.accept(f))
 8                 files.add(f);
 9         }
10         return files.toArray(new File[files.size()]);
11     }

為了便於理解,我下面上傳一張圖片來演示底層的調用

 

注意辣:如果給定的parent(一開始指定的)的文件目錄是有問題的,那么就會出現空指針異常.

 這樣的話,調用過程就比較清晰了.

 

最后,把程序改進以下,使得可以根據用戶的需求,更改篩選的目標,使可以篩選不同后綴名的文件.

可以通過文件過濾器的構造函數來傳遞這個表示后綴的參數

 1 public class MyFileFilter implements FileFilter{
 2     public String suffix;
 3     MyFileFilter(String suffix){
 4         this.suffix = suffix;
 5     }
 6     
 7     @Override
 8     public boolean accept(File pathname) {
 9         //
10         boolean matched = pathname.getName().endsWith(suffix);
11         boolean isFile = pathname.isFile();
12         return matched && isFile ;
13     }
14 
15 }
1 public static void main(String[] args) {
2         //創建父目錄File類的對象parent
3         File parent = new File("D:\\文檔\\瀏覽器下載");
4         //創建文件過濾器的對象
5         MyFileFilter fileFilter = new MyFileFilter(".exe");  //在創建對象的時候傳遞suffix的參數就可以了
6     }

 

 以上關於文件過濾器的理解已經比較透徹了.

總結一下吧:

可以使用FilenameFilter 和FileFilter過濾器,兩者中的accept函數所需要的參數不一樣,對應的操作也不一樣,FilenameFilter的accept需要兩個參數,而FileFilter的則是File對象

list(FilenameFilter filter)  返回的是string數組,其中存的就是滿足過濾器條件的子文件或者子文件夾

listFiles(FilenameFilter/FileFilter filter)  返回是對象數組,存的是滿足過濾器條件的File對象

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM