builder.createFileFilter(
                   "exam*.cpp;exam?.h",
                  "example Files(*.cpp;*.h)"));
 
           chooser.showOpenDialog(null);
 
仅仅是这几行代码就实现了第一个程序的功能,另外,还增加了一个选择cpp文件的功能和一个选择以exam开头的cpp文件或以exam开头的后跟一个字符的.h文件。下面,我将把我的设计介绍个大家。
 
从jsdk1.4开始,在java.util.regex出现了一个新的java类Pattern。Pattern是一个编译了的正则表达式的。它有很强大的功能,在这里我只使用其中一点点。在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]是一个你提供的regex,args[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();
    }
}