简体   繁体   中英

Java NIO Search file in a directory

I want to search a file(without knowing the full name) in a specific directory using Java NIO and glob.

public static void match(String glob, String location) throws IOException {

        final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(
                glob);

        Files.walkFileTree(Paths.get(location), new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult visitFile(Path path,
                    BasicFileAttributes attrs) throws IOException {
                if (pathMatcher.matches(path)) {
                    System.out.println(path);
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

Reading some tutorial I did this. I just want to return string if I find(first) file with given glob String.

if (pathMatcher.matches(path)) {
    return path.toString();
}

There are two things to be changed:

To " find(first) file with given glob String " you need to finish walking the tree if you encounter the file, thus if a match is given. And you need to store the matching path as result. The result of Files.walkFileTree itself is the "the starting file" ( JavaDoc ). That's a Path pointing to the location .

public static String match(String glob, String location) throws IOException {
    StringBuilder result = new StringBuilder();
    PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(glob);
    Files.walkFileTree(Paths.get(location), new SimpleFileVisitor<Path>() {

        @Override
        public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
            if (pathMatcher.matches(path)) {
                result.append(path.toString());
                return FileVisitResult.TERMINATE;
            }
            return FileVisitResult.CONTINUE;
        }
    });

    return result.toString();
}

If there is no match then the resulting String is empty.

EDIT:
Using Files.walk we can implement the search with less code still using a glob expression based matcher:

public static Optional<Path> match(String glob, String location) throws IOException {
    PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(glob);
    return Files.walk(Paths.get(location)).filter(pathMatcher::matches).findFirst();
}

The Optional as result shows that there may be no match.

Based on your own code. Just stop traversing once found some match

public class Main {

    private static Path found = "nothing"; // First file found

    public static void main(String[] args) throws IOException {
        String glob = "glob:**.{java}"; //pattern to look for
        String location = "D:\\"; //where to search
        match(location, glob);
        System.out.println("Found: " + found);
    }

    public static void match(String location, String glob) throws IOException {

        final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(glob);

        Files.walkFileTree(Paths.get(location), new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
                if (pathMatcher.matches(path)) {
                    found = path; // Match found, stop traversal
                    return FileVisitResult.TERMINATE;
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }
}

Or you can populate collection saving all the files matching the pattern

I don't know if this example could help you further, but it seems like you would need your own custom file visitor. Here is an alternative solution:

package com.jesperancinha.files;

import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

public class GlobFileVisitor extends SimpleFileVisitor<Path> {
    private final PathMatcher pathMatcher;

    private Path path;

    public GlobFileVisitor(String glob) {
        this.pathMatcher = FileSystems.getDefault().getPathMatcher(glob);
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
        if (pathMatcher.matches(path)) {
            this.path = path;
            return FileVisitResult.TERMINATE;
        }
        return FileVisitResult.CONTINUE;
    }

    public Path getFoundPath() {
        return path;
    }
}

And this is another possibility for your running example:

package com.jesperancinha.files;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileFinder {
    public static void main(String[] args) throws IOException {
        String glob = "glob:**.{java}";
        String location = "/Users/joao/dev/src/jesperancinha";
        Path found = match(location, glob);
        System.out.println("Found: " + found);
    }

    public static Path match(String location, String glob) throws IOException {
        GlobFileVisitor globFileVisitor = new GlobFileVisitor(glob);
        Files.walkFileTree(Paths.get(location), globFileVisitor);
        return globFileVisitor.getFoundPath();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM