使用Regex實現的爲JFileChooser使用的FileFilter對象的創建類

在使用swing的程序中經常用到JFileChooser,並且經常需要自定義一個FileFilter的子類來在文件列表中屏蔽不需要的文件。

 

大多數情況下,該子類是這樣設計的:

public ImgFileFilter

extends FileFilter{

    public boolean accept(File f) {

       if (f.isDirectory()) {

        return true;

       }

       // Utils is a user custom utility class, getExtension

       // is used to return the extension of a file.

        String extension = Utils.getExtension(f);

       if (extension != null) {

       if (extension.equals(Utils.tiff) ||

           extension.equals(Utils.tif) ||

           extension.equals(Utils.gif) ||

           extension.equals(Utils.jpeg) ||

           extension.equals(Utils.jpg) ||

           extension.equals(Utils.png)) {

               return true;

       } else {

           return false;

       }

       }

        return false;

    }

    public boolean getDescription(){

        return "Image Files.";

    }

}

 

這段代碼取自sun公司的"Java Tutorial". 正象你所看到的accept(File file)方法決定一個文件是否顯示如果返回值爲true則顯示反之屏蔽。

麻煩的是如果你要使用多項文件類型選擇,比如在EditPluse裏,你可以選擇打開*.txt, *.cpp, *.java等文件。爲了這類需求,你不得不一個一個爲不同的文件選擇設計不同的FileFilter。有沒有更方便的方法來實現FileFilter呢?我設計了一個工具類可以解決這個問題,使用它,幾行代碼就可以完成一個JFileChooser的設計:

 

    JFileChooser chooser = new JFileChooser();

    FileFilterBuilder builder = FileFilterBuilder.newInstance().

           chooser.setFileFilter(

               builder.createFileFilter(

                   "*.tiff;*.tif;*.gif;*.jpeg;*.jpg;*.png"

                   ,"Image Files(*.tiff;*.tif;*.gif;*.jpeg;*.jpg;*.png)"));

           chooser.setFileFilter(

               builder.createFileFilter(

                   "*.cpp;*.h",

                  "Cpp Files(*.cpp;*.h)"));

           chooser.setFileFilter(

               builder.createFileFilter(

                   "exam*.cpp;exam?.h",

                  "example Files(*.cpp;*.h)"));

 

           chooser.showOpenDialog(null);

 

僅僅是這幾行代碼就實現了第一個程序的功能,另外,還增加了一個選擇cpp文件的功能和一個選擇以exam開頭的cpp文件或以exam開頭的後跟一個字符的.h文件。下面,我將把我的設計介紹個大家。

 

jsdk1.4開始,在java.util.regex出現了一個新的javaPatternPattern是一個編譯了的正則表達式的。它有很強大的功能,在這裏我只使用其中一點點。在Pattern類中有一個方法matches(String regex, CharSequence input)可以判斷是否一個input可以與一個regex向符合。"regex""regular expression"的縮寫, 一個正則表達式是一個字符串模型, Windows中文件名模型一樣, 比如, "*.exe" 就是一個可以包括所有可執行文件的文件名模型。

 

到這裏,你會猜到我要做什麼了。首先,我介紹幾個程序中用到的regex的特徵。

 

在一個regex中,字符"."代表任何一個字符,".*"代表零個或多個字符,".{n}"代表n個任意字符。我們可以作一個測試。

import java.util.regex.Pattern;

public class TestRegex {

    public static void main(String[] args) {

        String regex, input;

 

       regex = args[0];

       input = args[1];

        boolean isMatch = Pattern.matches(regex, input);

 

        System.out.println(isMatch);

    }

}

 

上面代碼中args[0]是一個你提供的regexargs[1]是一個待判定的字符串如果該字符串與regex相符程序將打印True否則false。通過提供不同的運行參數並查看運行結果,可以幫助你瞭解regex

 

我們知道,在windows文件名模型中"?"代表一個字符,與regex中的".{1}"相對應;"*"代表0個或多個字符,與regex中的".*"相對應。如果一個字符串中包含"????",那麼,對應的,我們可以在regex中使用".{4}"與之匹配。最後一個重要的事情是對於字符"."regex應該使用"[.]"與之對應。

 

好了,事情結束了,正象你所猜測的,我的設計的核心是把windows的文件名模型轉換成regex,然後使用這個regex來決定那些文件可以顯示,那些文件不顯示。下面列出所有代碼。

 

/*

 * @(#)FileFilterBuilder.java  1.0 06/01/03

 * @author Unagain

 */

 

package je14tut.dom;

 

import java.io.File;

import java.util.regex.Pattern;

 

import javax.swing.filechooser.FileFilter;

 

/**

 * The <code>FileFilterBuilder</code> class is a singleton, it can create

 * a appropriate <code>FilterFilter</code> object for a <code>JFileChooser</code> object

 * in your code, rather than to write a subclass of FileFilter manually.

 * <p>

 * You can use <code>newInstance</code> to obtain the only instance, and use

 * <code>createFileFilter</code> to get the <code>FileFilter</code>.

 *

 * @author Jason

 *

 */

 

public class FileFilterBuilder {

    static FileFilterBuilder INSTANCE;

   

    static final int NAME = 0;

    static final int EXT = 1;

 

    private FileFilterBuilder() {}

   

    /**

     * create and get the singleton instance.

     * @return FileterBuilder.

     */

   

    public static FileFilterBuilder newInstance() {

        if (INSTANCE == null) {

            INSTANCE = new FileFilterBuilder();

        }

        return INSTANCE;

    }

   

    /**

     * The only functional method in this class so far, used to create a appropriate

     * <code>FileFilter</code> instance you perferred based on a windows system file pattern

     * you given.

     *

     * @param winFilePattern - A window system file pattern, such as "*.java", "new*.*",

     * "ex?mp*.exe", etc.

     * <blockquote>you can specified two or more pattern once, split each other with ";", for example

     * "*.java;*.html", etc. </blockquote>

     * @param description

     * @return

     */

   

    public FileFilter createFileFilter(String winFilePattern, final String description) {

   

    final String pattern = PatternBuilder.createFileRegex(winFilePattern);

   

        FileFilter filter =

            new FileFilter() {

                 

                public boolean accept(File f) {

                  if (f.isDirectory()) {

                      return true;

                  }

                  return Pattern.matches(pattern, f.getName().toLowerCase());

              }

                public String getDescription() {

                  return description;

              }

        };

        return filter;

    }

}

 

/**

 * <code>PatternBuilder</code> has only one methoes so far, it just as a translator to convert a

 * windows system file pattern to a java regular expression for <code>FileFilterBuiolder</code>.

 * In fact it is more power than FileFilter needed, for Considering possibly usage in future, I

 *  separate it from <code>FileFilterBuiolder</code>.

 * @author Jason

 */

class PatternBuilder {

    private PatternBuilder() {}

   

    public static String createFileRegex(String filePattern) {

   

        StringBuffer regex = new StringBuffer();

        boolean lastIsQueMark = false;

        int queMarkCount = 0;

       

        filePattern = filePattern.toLowerCase();

       

        for (int i=0; i<filePattern.length(); i++) {

        char chr = filePattern.charAt(i);

       

        if (chr == '?') {

                if (!lastIsQueMark) {

                    regex.append(".{");               

                    lastIsQueMark = true;               

              }

                queMarkCount ++;

        } else {

            

                if (lastIsQueMark) {               

                  regex.append(queMarkCount);

                  regex.append("}");                  

                  queMarkCount = 0;

                  lastIsQueMark = false;

              }

             

                switch(chr){

                case '*':

                    regex.append(".*");

                    break;

                case '.':

                    regex.append("[.]");

                    break;

                case ';':

                    regex.append("|");

                    break;

                default:                   

                    regex.append(chr);

                }

        }

       

        }

       

        return regex.toString();

    }

}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章