Skip to main content

Recursive file search and still filtering file and directory names?

1 reply [Last post]
Joined: 2009-01-29
Points: 0


Can any one help me with the code below?

The first problem with it, and the more important, is that if I don't check for directories in the filter, the code will not work, because the content (subdirectories and theirs content) won't be traversed, but if I do check I'll get directories from the search which were not supposed to be returned. I don't want to add another filter into the callbacks (public void onDirectory(final File f)) as it will degrade the code's quality (not as it were brilliant code :rolling: ).

The second problem is the onFile(f); line. I think as I start the search always with a DIRECTORY it won't get here if it's not a filtered file. I couldn't get proofs from a few tests I did, so it seems OK. What do you guys think?

The third problem is about performance, I know recursive code is not the best one out there regarding performance(although it is elegant and reasonably simple to understand). Is there any simple alternative with better performance?

Any other tip would be much appreciated. :)


/*<br />
 * To change this template, choose Tools | Templates<br />
 * and open the template in the editor.<br />
 */<br />
package javaapplication4;</p>
<p>import;<br />
import;<br />
import;<br />
import java.util.regex.Pattern;</p>
<p>public class Main {</p>
<p>    /**<br />
     * @param args the command line arguments<br />
     */<br />
    static FileTraversal f = null;<br />
    static int countFile = 0;<br />
    static int countDir = 0;</p>
<p>    public static void main(String[] args) throws IOException {</p>
<p>        new FileTraversal() {</p>
<p>            public void onFile(final File f) {<br />
                countFile++;<br />
                System.out.println("File: " + f.getAbsolutePath());<br />
<p>            public void onDirectory(final File f) {<br />
                countDir++;<br />
                System.out.println("Directory: " + f.getAbsolutePath());<br />
            }<br />
        }.traverse(new File("/"));</p>
<p>        System.out.println("Total: " + countFile + " -> " + countDir + " = " + (countFile + countDir));<br />
<p>    public static class FileTraversal {</p>
<p>        public final void traverse(final File f) throws IOException {<br />
            if (f.isDirectory()) {<br />
                onDirectory(f);<br />
                FileFilter filter = new RegExpFilter(wildcardToRegex("pa*.txt"));<br />
                final File[] childs = f.listFiles(filter);<br />
                if (childs != null) {<br />
                    for (File child : childs) {<br />
                        traverse(child);<br />
                    }<br />
                }<br />
                return;<br />
            }<br />
           ***onFile(f);***//What's the more elegant approach to solve that problem?<br />
<p>        public static String wildcardToRegex(String wildcard) {<br />
            StringBuffer s = new StringBuffer(wildcard.length());<br />
            s.append('^');<br />
            for (int i = 0, is = wildcard.length(); i < is; i++) {<br />
                char c = wildcard.charAt(i);<br />
                switch (c) {<br />
                    case '*':<br />
                        s.append(".*");<br />
                        break;<br />
                    case '?':<br />
                        s.append(".");<br />
                        break;<br />
                    // escape special regexp-characters<br />
                    case '(':<br />
                    case ')':<br />
                    case '[':<br />
                    case ']':<br />
                    case '$':<br />
                    case '^':<br />
                    case '.':<br />
                    case '{':<br />
                    case '}':<br />
                    case '|':<br />
                    case '\\':<br />
                        s.append("\\");<br />
                        s.append(c);<br />
                        break;<br />
                    default:<br />
                        s.append(c);<br />
                        break;<br />
                }<br />
            }<br />
            s.append('$');<br />
            return (s.toString());<br />
<p>        public void onDirectory(final File d) {<br />
<p>        public void onFile(final File f) {<br />
        }<br />
    }<br />
<p>class RegExpFilter implements FileFilter {</p>
<p>    private Pattern pattern;</p>
<p>    public RegExpFilter(String regex) {<br />
        pattern = Pattern.compile(regex);<br />
<p>    public boolean accept(File pathname) {<br />
     ***if (pathname.isDirectory()) //?????<br />
        {<br />
            return true;<br />
        }***<br />
        return pattern.matcher(pathname.getName()).matches();<br />
    }<br />

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joined: 2005-08-08
Points: 0

You might want to look as FileVisitor and Files.walkFileTree in jdk7. It also PathMatcher that supports globs and does the right thing for each platform.