在使用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出现了一个新的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来决定那些文件可以显示,那些文件不显示。下面列出所有代码。