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();
}
}