Apache commons IO包中提供了一个可以遍历目录下资源的DirectoryWalker,还有很多的IOFileFilter用于过滤文件目录。下面的例子分别演示了这个功能。
这两个搜索类都是以内部类的方式嵌入客户端的,客户端接收客户的参数,然后通过一个后台线程来进行搜索,等待子线程完成搜索后(join方法),再打印搜索结果。
注意这个过程是可以被cancel的。cancel主要有2种情况。外部cancel:外部线程通过调用内部类的cancel()方法。内部cancel:在handleDirectory、handleFile中主动抛出CancelException。
walk方法在每次执行前、后都会检查当前是否有cancel指令发出(checkIfCancelled ---> handleIsCancelled),如果有那么默认立刻抛出CancelException,然后调用handleCancelled方法。
这里搜索实现类被实现为一个内部类,目的是不想暴露内部的搜索过程逻辑,只对外暴露客户端接口。其次内部采用线程实现,方便充当客户端的外部类可以在必要时cancel这个内部线程操作,而且当搜索过程漫长时不会造成界面假死(GUI界面)。
在搜索过程中,我们可以对搜索到文件、资源进行处理,例如:删除,重命名,移动等。最常见的一个应用就是批量删除搜索到的文件。例如.svn目录或日志文件
/** *//**
* Main recursive method to examine the directory hierarchy.
*
* @param directory the directory to examine, not null
* @param depth the directory level (starting directory = 0)
* @param results the collection of result objects, may be updated
* @throws IOException if an I/O Error occurs
*/
private void walk(File directory, int depth, Collection results) throws IOException {
checkIfCancelled(directory, depth, results);
if (handleDirectory(directory, depth, results)) {
handleDirectoryStart(directory, depth, results);
int childDepth = depth + 1;
if (depthLimit < 0 || childDepth <= depthLimit) {
checkIfCancelled(directory, depth, results);
File[] childFiles = (filter == null ? directory.listFiles() : directory.listFiles(filter));
if (childFiles == null) {
handleRestricted(directory, childDepth, results);
} else {
for (int i = 0; i < childFiles.length; i++) {
File childFile = childFiles[i];
if (childFile.isDirectory()) {
walk(childFile, childDepth, results);
} else {
checkIfCancelled(childFile, childDepth, results);
handleFile(childFile, childDepth, results);
checkIfCancelled(childFile, childDepth, results);
}
}
}
}
handleDirectoryEnd(directory, depth, results);
}
checkIfCancelled(directory, depth, results);
}
【一】从根目录开始,查询(指定目录下)指定的文件
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
/**
* The Class FileSearcher.
*/
public class FileSearcher {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
String baseDir = null;
String targetDir = null;
String targetFile = null;
if (args == null || args.length == 0) {
System.err.println("Error: Missing start directory name");
System.exit(-1);
}
if (args == null || args.length == 1) {
System.err.println("Error: Missing target file name");
System.exit(-1);
}
FileSearcher searcher = new FileSearcher();
// Only base directory and file name are given
if (args != null && args.length == 2) {
baseDir = args[0];
targetFile = args[1];
searcher.search(baseDir, targetFile);
}
// Both base and parent directories name and file name are given
if (args != null && args.length >= 3) {
baseDir = args[0];
targetDir = args[1];
targetFile = args[2];
searcher.search(baseDir, targetDir, targetFile);
}
}
/**
* Search by file name
*
* @param baseDir
* the base dir
* @param targetFile
* the target file
*/
public void search(String baseDir, String targetFile) {
search(baseDir, null, targetFile);
}
/**
* Search by file name and parent directory name
*
* @param baseDir
* the base dir
* @param targetDir
* the target dir
* @param targetFile
* the target file
*/
public void search(String baseDir, String targetDir, String targetFile) {
// File existence check
if ((baseDir == null || baseDir.trim().length() == 0)
|| (targetFile == null || (targetFile.trim().length() == 0))) {
System.err.println("Error: Missing base directory or file name");
System.exit(-1);
}
File startDirectory = new File(baseDir);
if (!startDirectory.exists()) {
System.err.println("Error: Couldn't find path by given parameter");
System.exit(-1);
}
// Create a new thread and start to search
SearchFileWalker walker = new SearchFileWalker(startDirectory,
targetDir, targetFile);
Thread searchThread = new Thread(walker);
searchThread.start();
System.out.println("Start to search ");
try {
searchThread.join(); // child thread join to main thread
} catch (InterruptedException e) {
e.printStackTrace();
}
walker.displaySearchResult();
}
class SearchFileWalker extends DirectoryWalker implements Runnable {
private volatile boolean cancelled = false;
private boolean matchByFileNameOnly = true;
private File baseDir;
private String targetDirName;
private String targetFileName;
private List<File> finalResult = new ArrayList<File>();
/**
* Instantiates a new search directory walker.
*
* @param startDir
* the start dir
* @param targetFile
* the target file
*/
public SearchFileWalker(File startDir, String targetFile) {
this(startDir, null, targetFile);
}
/**
* Instantiates a new search directory walker.
*
* @param startDir
* the start dir
* @param targetDir
* the target dir
* @param targetFile
* the target file
*/
public SearchFileWalker(File startDir, String targetDir,
String targetFile) {
super();
baseDir = startDir;
targetDirName = targetDir;
targetFileName = targetFile;
matchByFileNameOnly = (targetDirName == null) ? true : false;
}
/**
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
search();
}
/**
* Search.
*/
public void search() {
List<File> searchResult = new ArrayList<File>();
try {
walk(baseDir, searchResult);
} catch (IOException e) {
e.printStackTrace();
}
finalResult = searchResult;
}
/**
* Gets the result.
*
* @return the result
*/
public List<File> getResult() {
return finalResult;
}
/**
* Display search result.
*/
public void displaySearchResult() {
File f = null;
System.out.println("\n=======================================");
for (int i = 0; i < finalResult.size(); i++) {
f = (File) finalResult.get(i);
System.out.println(" File found: " + f.getAbsolutePath());
}
System.out.println("=======================================\n");
}
/**
* (non-Javadoc)
*
* @see org.apache.commons.io.DirectoryWalker#handleDirectory(java.io.File,
* int, java.util.Collection)
*/
protected boolean handleDirectory(File directory, int depth,
Collection results) throws IOException {
System.out.println("\nSearching under directory: "
+ directory.getAbsolutePath());
if (matchByFileNameOnly) {
return true; // Match by file name only
} else if (FilenameUtils.equalsNormalizedOnSystem(targetDirName,
directory.getName())) {
return true; // Parent directory name matched
} else if (directory.list(FileFilterUtils.directoryFileFilter()).length > 0) {
return true; // Has child directory
} else {
return false; // Empty directory or file name doesn't match
}
}
/**
* (non-Javadoc)
*
* @see org.apache.commons.io.DirectoryWalker#handleFile(java.io.File,
* int, java.util.Collection)
*/
protected void handleFile(File file, int depth, Collection results)
throws IOException {
// Matches by file name only
if (targetFileName.equals(file.getName()) && matchByFileNameOnly) {
results.add(file);
}
// Matches by directory name and file name
if (FilenameUtils.equalsNormalizedOnSystem(targetFileName,
file.getName())
&& (!matchByFileNameOnly)) {
String fullPath = FilenameUtils.getFullPathNoEndSeparator(file
.getAbsolutePath());
String fileParentDir = fullPath.substring(FilenameUtils
.indexOfLastSeparator(fullPath) + 1);
if (FilenameUtils.equalsOnSystem(targetDirName, fileParentDir)) {
results.add(file);
}
}
}
/**
* Cancel.
*/
public void cancel() {
cancelled = true;
}
/**
* (non-Javadoc)
*
* @see org.apache.commons.io.DirectoryWalker#handleIsCancelled(java.io.File,
* int, java.util.Collection)
*/
protected boolean handleIsCancelled(File file, int depth,
Collection results) {
return cancelled;
}
/**
* (non-Javadoc)
*
* @see org.apache.commons.io.DirectoryWalker#handleCancelled(java.io.File,
* java.util.Collection,
* org.apache.commons.io.DirectoryWalker.CancelException)
*/
protected void handleCancelled(File startDirectory, Collection results,
CancelException cancel) {
if (cancelled) {
cancel();
}
System.out.println("\nCancelled by external or interal thread");
finalResult = (List<File>) results;
}
}
}
【二】从根目录开始,查找指定的目录
package example.io;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
/** *//**
* The Class DirectorySearcher.
*/
public class DirectorySearcher {
/** *//**
* The main method.
*
* @param args the arguments
*/
public static void main(String[] args) {
String baseDir = null;
String targetDir = null;
if (args == null || args.length == 0) {
System.err.println("Error: Missing start directory name");
System.exit(-1);
}
if (args == null || args.length == 1) {
System.err.println("Error: Missing target directory name");
System.exit(-1);
}
baseDir = args[0];
targetDir = args[1];
DirectorySearcher searcher = new DirectorySearcher();
searcher.search(baseDir, targetDir);
}
/** *//**
* Search by directory name
*
* @param baseDir the base dir
* @param targetDir the target dir
*/
public void search(String baseDir, String targetDir) {
// File existence check
if ((baseDir == null || baseDir.trim().length() == 0)
|| (targetDir == null || (targetDir.trim().length() == 0))) {
System.err.println("Error: Missing base or target directory name");
System.exit(-1);
}
File startDirectory = new File(baseDir);
if (!startDirectory.exists()) {
System.err.println("Error: Couldn't find path by given parameter");
System.exit(-1);
}
// Create a new thread and start to search
SearchDirectoryWalker walker = new SearchDirectoryWalker(
startDirectory, targetDir);
Thread searchThread = new Thread(walker);
searchThread.start();
System.out.println("Start to search ");
try {
searchThread.join(); // child thread join to main thread
} catch (InterruptedException e) {
e.printStackTrace();
}
walker.displaySearchResult();
}
/** *//**
* The Class SearchDirectoryWalker.
*/
class SearchDirectoryWalker extends DirectoryWalker implements Runnable {
private volatile boolean cancelled = false;
private File baseDir;
private String targetDirName;
private List<File> finalResult = new ArrayList<File>();
/** *//**
* Instantiates a new search directory walker.
*
* @param startDir the start dir
* @param targetDir the target dir
*/
public SearchDirectoryWalker(File startDir, String targetDir) {
super(FileFilterUtils.directoryFileFilter(), -1);
baseDir = startDir;
targetDirName = targetDir;
}
/**//*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
search();
}
/** *//**
* Search.
*/
public void search() {
List<File> searchResult = new ArrayList<File>();
try {
walk(baseDir, searchResult);
} catch (IOException e) {
e.printStackTrace();
}
finalResult = searchResult;
}
/** *//**
* Gets the result.
*
* @return the result
*/
public List<File> getResult() {
return finalResult;
}
/** *//**
* Display search result.
*/
public void displaySearchResult() {
File f = null;
System.out.println("\n=======================================");
for (int i = 0; i < finalResult.size(); i++) {
f = (File) finalResult.get(i);
System.out.println(" Directory found: " + f.getAbsolutePath());
}
System.out.println("=======================================\n");
}
/**//*
* (non-Javadoc)
*
* @see org.apache.commons.io.DirectoryWalker#handleDirectory(java.io.File,
* int, java.util.Collection)
*/
protected boolean handleDirectory(File directory, int depth,
Collection results) throws IOException {
System.out.println("\nSearching under directory: "
+ directory.getAbsolutePath());
// Just test for cancel operation
// Cancel when meet WebRoot folder, so all directories under this
// folder are supposed not to be check
if (FilenameUtils.equalsNormalizedOnSystem("WebRoot", directory
.getName())) {
throw new CancelException(directory, depth);
}
if (FilenameUtils.equalsNormalizedOnSystem(targetDirName, directory
.getName())) {
results.add(directory);
}
return true;
}
/** *//**
* Cancel.
*/
public void cancel() {
cancelled = true;
}
/**//*
* (non-Javadoc)
*
* @see org.apache.commons.io.DirectoryWalker#handleIsCancelled(java.io.File,
* int, java.util.Collection)
*/
protected boolean handleIsCancelled(File file, int depth,
Collection results) {
return cancelled;
}
/**//*
* (non-Javadoc)
*
* @see org.apache.commons.io.DirectoryWalker#handleCancelled(java.io.File,
* java.util.Collection,
* org.apache.commons.io.DirectoryWalker.CancelException)
*/
protected void handleCancelled(File startDirectory, Collection results,
CancelException cancel) {
if (cancelled) {
cancel();
}
System.out.println("\nCancelled by external or interal thread");
finalResult = (List<File>) results;
}
}
}