在使用swing的程序中经常用到JFileChooser,并且经常需要自定义一个FileFilter的子类来在文件列表中屏蔽不需要的文件。<o:p></o:p>
<o:p></o:p>
大多数情况下,该子类是这样设计的:<o:p></o:p>
public ImgFileFilter<o:p></o:p>
extends FileFilter{<o:p></o:p>
public boolean accept(File f) {<o:p></o:p>
if (f.isDirectory()) {<o:p></o:p>
return true;<o:p></o:p>
}<o:p></o:p>
// Utils is a user custom utility class, getExtension<o:p></o:p>
// is used to return the extension of a file.<o:p></o:p>
String extension = Utils.getExtension(f);<o:p></o:p>
if (extension != null) {<o:p></o:p>
if (extension.equals(Utils.tiff) ||<o:p></o:p>
extension.equals(Utils.tif) ||<o:p></o:p>
extension.equals(Utils.gif) ||<o:p></o:p>
extension.equals(Utils.jpeg) ||<o:p></o:p>
extension.equals(Utils.jpg) ||<o:p></o:p>
extension.equals(Utils.png)) {<o:p></o:p>
return true;<o:p></o:p>
} else {<o:p></o:p>
return false;<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
return false;<o:p></o:p>
}<o:p></o:p>
public boolean getDescription(){<o:p></o:p>
return "Image Files.";<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p></o:p>
这段代码取自sun公司的"Java Tutorial". 正象你所看到的,accept(File file)方法决定一个文件是否显示,如果返回值为true,则显示,反之,屏蔽。<o:p></o:p>
麻烦的是如果你要使用多项文件类型选择,比如在EditPluse里,你可以选择打开*.txt, *.cpp, *.java等文件。为了这类需求,你不得不一个一个为不同的文件选择设计不同的FileFilter。有没有更方便的方法来实现FileFilter呢?我设计了一个工具类可以解决这个问题,使用它,几行代码就可以完成一个JFileChooser的设计:<o:p></o:p>
<o:p></o:p>
JFileChooser chooser = new JFileChooser();<o:p></o:p>
FileFilterBuilder builder = FileFilterBuilder.newInstance().<o:p></o:p>
chooser.setFileFilter(<o:p></o:p>
builder.createFileFilter(<o:p></o:p>
"*.tiff;*.tif;*.gif;*.jpeg;*.jpg;*.png"<o:p></o:p>
,"Image Files(*.tiff;*.tif;*.gif;*.jpeg;*.jpg;*.png)"));<o:p></o:p>
chooser.setFileFilter(<o:p></o:p>
builder.createFileFilter(<o:p></o:p>
"*.cpp;*.h",<o:p></o:p>
"Cpp Files(*.cpp;*.h)"));
<o:p> chooser.setFileFilter(</o:p>
<o:p>builder.createFileFilter(<o:p></o:p>
"exam*.cpp;exam?.h",<o:p></o:p>
"example Files(*.cpp;*.h)"));
chooser.showOpenDialog(null);<o:p></o:p>
<o:p></o:p>
仅仅是这几行代码就实现了第一个程序的功能,另外,还增加了一个选择cpp文件的功能和一个选择以exam开头的cpp文件或以exam开头的后跟一个字符的.h文件。下面,我将把我的设计介绍个大家。<o:p></o:p>
<o:p></o:p>
从jsdk1.4开始,在java.util.regex出现了一个新的java类Pattern。Pattern是一个编译了的正则表达式的。它有很强大的功能,在这里我只使用其中一点点。在Pattern类中有一个方法matches(String regex, CharSequence input)可以判断是否一个input可以与一个regex向符合。"regex"是"regular expression"的缩写, 一个正则表达式是一个字符串模型, 和Windows中文件名模型一样, 比如, "*.exe" 就是一个可以包括所有可执行文件的文件名模型。<o:p></o:p>
<o:p></o:p>
到这里,你会猜到我要做什么了。首先,我介绍几个程序中用到的regex的特征。<o:p></o:p>
<o:p></o:p>
在一个regex中,字符"."代表任何一个字符,".*"代表零个或多个字符,".{n}"代表n个任意字符。我们可以作一个测试。<o:p></o:p>
import java.util.regex.Pattern;<o:p></o:p>
public class TestRegex {<o:p></o:p>
public static void main(String[] args) {<o:p></o:p>
String regex, input;<o:p></o:p>
<o:p></o:p>
regex = args[0];<o:p></o:p>
input = args[1];<o:p></o:p>
boolean isMatch = Pattern.matches(regex, input);<o:p></o:p>
<o:p></o:p>
System.out.println(isMatch);<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p></o:p>
上面代码中,args[0]是一个你提供的regex,args[1]是一个待判定的字符串,如果该字符串与regex相符,程序将打印True,否则,false。通过提供不同的运行参数并查看运行结果,可以帮助你了解regex。<o:p></o:p>
<o:p></o:p>
我们知道,在windows文件名模型中"?"代表一个字符,与regex中的".{1}"相对应;"*"代表0个或多个字符,与regex中的".*"相对应。如果一个字符串中包含"????",那么,对应的,我们可以在regex中使用".{4}"与之匹配。最后一个重要的事情是对于字符".",regex应该使用"[.]"与之对应。<o:p></o:p>
<o:p></o:p>
好了,事情结束了,正象你所猜测的,我的设计的核心是把windows的文件名模型转换成regex,然后使用这个regex来决定那些文件可以显示,那些文件不显示。下面列出所有代码。
</o:p>