`
sunxboy
  • 浏览: 2869279 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

使用DirectoryWalker和FileFilterUtils进行搜索

阅读更多

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

}
分享到:
评论

相关推荐

    Io框架 commons-io

    - `SerializationUtils` 提供了对象序列化和反序列化的简单接口,方便进行对象持久化存储。 - `FileObjectSerializer` 和 `FileObjectDeserializer` 专门用于文件系统上的对象序列化和反序列化。 5. 常用工具: ...

    commons_io

    9. **FileFilterUtils**: 提供了多种文件过滤器,可以用来筛选出满足特定条件的文件,如按名字、大小、日期等进行过滤。 10. **DirectoryWalker**: 这是一个接口,可以实现对目录及其子目录的深度优先或广度优先...

    commons-io.zip

    - `FileFilterUtils`: 提供了一组方便的文件过滤器,如按名字、扩展名、大小等进行过滤。 - `IOFileFilter`: 继承自Java的`FileFilter`和`FilenameFilter`,提供了更灵活的文件过滤机制。 8. **线程安全** - `...

    可以看成是java.io的扩展。它提供了文件阅读功能,以及一些使用的方法

    5. **DirectoryWalker**: 这是一个抽象类,用于遍历目录及其子目录中的所有文件,可以根据需求进行定制,过滤特定类型的文件或执行特定操作。 6. **LineIterator**: 该迭代器用于逐行读取文件,非常适合处理大型...

    commons-io-2.11.0.rar

    Apache Commons IO 是一个Java库,专门用于处理输入/输出(I/O)操作。这个库提供了大量的实用工具类,简化了常见的文件、流、...通过深入学习和使用这个库,开发者可以更好地理解和管理文件和流操作,提升代码质量。

    commons-io-2.5 jar包.rar

    8. **DirectoryWalker**: 这是一个接口,可以用于遍历目录树,实现自定义的文件搜索和处理逻辑。 9. **EndianSwappedDataInputStream** 和 **EndianSwappedDataOutputStream**: 这两个类用于处理字节顺序与当前系统...

    commons io 源代码

    Apache Commons IO 是一个Java库,提供了大量的工具类来处理日常...此外,源代码还展示了如何利用Java的异常处理机制,以及如何进行单元测试和文档编写。这不仅有助于提升个人技能,也有助于在实际项目中应用最佳实践。

    commons-io-2.2-bin.zip

    3. **迭代器**:如`FileIterator`和`DirectoryWalker`,它们允许开发者以迭代的方式遍历文件系统中的文件和目录,这在需要处理大量文件时特别有用。 4. **文件过滤器**:`FileFilter`和`IOFileFilter`接口提供了...

    Commons-io-fileload源码和组件

    4. **DirectoryWalker**: 实现了遍历目录及其子目录的功能,可以自定义过滤器,方便进行文件查找和处理。 查看 `commons-io-2.6-src.zip` 源码,我们可以了解这些类的内部实现,学习如何优雅地处理I/O操作。 **...

    commons-io-2.3-bin

    7. **过滤与选择**:`FilenameFilter`和`DirectoryWalker`接口允许用户根据特定规则筛选文件和目录,例如按扩展名筛选文件。 8. **文件分块读写**:对于大文件,`FileUtils.copyFileToChannels`和`FileUtils....

    commons-io-2.11.0.jar

    6. **迭代器**:DirectoryWalker 和 FilenameFilterIterator 可以迭代目录中的文件,便于遍历和处理目录结构。 7. **文件观察**:FileAlterationObserver 和 FileAlterationListener API 可以监控文件系统的变动,...

    commmons-io2.6 2.7 Downloads.rar

    此外,还有`LineIterator` 类,可以方便地逐行读取文件,而`DirectoryWalker` 类则允许你遍历整个目录树进行自定义操作。 接下来,`commons-io-2.7-bin.zip` 文件包含了Apache Commons IO的2.7版本。此版本相较于...

    commons-io架包+文档.zip

    3. **目录(Directory)**:`DirectoryWalker`类允许遍历目录树,`FileVisitor`接口(Java 7及以上版本)提供了一种更现代的方式进行文件系统遍历。 4. **读写(Read and Write)**:`LineIterator`类用于逐行读取文本...

    commons-io-2.4.jar

    2. **InputStreamReader/OutputStreamWriter**: Commons IO库对这些基础的读写流进行了扩展,增加了如`BufferedInputStream`和`BufferedOutputStream`等类,可以提高数据传输效率并减少系统调用。还有`...

    commons-io文件

    Apache Commons IO 是一个Java库,专门用于处理输入/输出(I/O)操作。...这个库在各种项目和框架中广泛使用,是Java开发者的强大工具。在`2.11.0`版本中,开发者可以期待更多的稳定性和性能优化。

    java 文件管理集合

    8. **Directories**:`java.nio.file.DirectoryStream` 和 `java.nio.file.DirectoryWalker` 可用于遍历目录及其子目录,获取所有文件和子目录的信息。 9. **文件权限**:`java.nio.file.attribute....

    commons-io-2.0-src

    这个版本的源代码对于学习和理解库的内部工作原理,或者进行自定义扩展非常有帮助。 在Apache Commons IO 2.0中,我们可以找到以下几个关键的知识点: 1. **IOUtils**: 这是Apache Commons IO的核心类之一,提供了...

    commons-io-2.6--java框架技术

    - `DirectoryWalker`: 用于递归遍历目录,可以自定义处理文件和子目录的逻辑。 - ` FilenameUtils`和`PathUtils`: 提供了与文件名和路径相关的操作,例如获取扩展名、判断路径是否为绝对路径等。 2. **流处理**:...

    commons-io-2.0.jar

    `StringInputStream`和`StringOutputStream`允许在字符串和流之间进行灵活转换。 4. **字符集**:在处理编码和解码时,`Charsets`类提供了对常见字符集的便捷访问,如UTF-8、ISO-8859-1等,避免了直接依赖Java的...

    commons-io-2.6.jar

    例如,`FileUtils.copyFile()`和`FileUtils.moveFile()`可以方便地实现文件的复制和移动,而`DirectoryWalker`类则用于遍历目录结构,执行自定义操作。 2. 文件比较:`FileCompare`类提供了比较两个文件或两个目录...

Global site tag (gtag.js) - Google Analytics