001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit https://imagingbook.com for additional details. 008 ******************************************************************************/ 009package imagingbook.common.util; 010 011import java.io.IOException; 012import java.nio.file.FileVisitResult; 013import java.nio.file.Files; 014import java.nio.file.Path; 015import java.nio.file.Paths; 016import java.nio.file.SimpleFileVisitor; 017import java.nio.file.attribute.BasicFileAttributes; 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.List; 021 022/** 023 * Modern-style directory traversal. Requires Java 1.7 or higher! 024 * 025 * @author WB 026 * @version 2016/04/05 027 * 028 */ 029public class DirectoryWalker { 030 031 private final List<String> fileList; 032 private final String[] extensions; 033 034 /** 035 * Constructor. 036 * 037 * @param extensions a sequence of file extensions like ".jpg", ".gif", ".tif" etc. Note that extensions are case 038 * sensitive, i.e., multiple extensions must be supplied if upper/lower case extensions should be considered. Supply 039 * {@code null} to accept *any* file extension. 040 */ 041 public DirectoryWalker(String... extensions) { 042 this.fileList = new ArrayList<String>(); 043 this.extensions = extensions; 044 } 045 046 /** 047 * Use this method to recursively collect all files with the initially specified extensions, starting from the given 048 * directory. 049 * TODO: clean up exception handling. 050 * 051 * @param startDir The start directory. 052 * @return A list of file names. 053 */ 054 public Collection<String> collectFiles(String startDir) { 055 try { 056 this.traverse(Paths.get(startDir)); 057 } catch (IOException e) { } 058 return this.fileList; 059 } 060 061 /** 062 * Traverses the directory tree and collects all matching file names. 063 * 064 * @param startDir start directory 065 * @throws IOException 066 */ 067 private void traverse(Path startDir) throws IOException { 068 // TODO: clean up exception handling. 069 Files.walkFileTree(startDir, new SimpleFileVisitor<Path>() { 070 @Override 071 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 072 String pathName = file.toString(); 073 if (hasMatchingExtension(pathName)) { 074 fileList.add(pathName); 075 // System.out.println("added file " + file.toString()); 076 } 077 return FileVisitResult.CONTINUE; 078 } 079 @Override 080 public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { 081 if (e == null) { 082 //System.out.println("visiting " + dir.toString()); 083 return FileVisitResult.CONTINUE; 084 } else { 085 // directory iteration failed 086 throw e; 087 } 088 } 089 }); 090 } 091 092 /** 093 * Checks if the pathName has any of the specified extensions. This is case sensitive! 094 * 095 * @param pathName 096 * @return true if the path name matches one of the specified extensions 097 */ 098 private boolean hasMatchingExtension(String pathName) { 099 if (extensions == null || extensions.length == 0) 100 return true; 101 boolean result = false; 102 for (String s : extensions) { 103 if (pathName.endsWith(s)) { 104 result = true; 105 break; 106 } 107 } 108 return result; 109 } 110 111}