Search code examples
javasearchnullpointerexceptionnionio2

Why do I see NullPointerException when I search files by mask under the root folder ?(windows)


I investigate java nio2 possibilities.

I knew that I can search files using FileVisitor interface. To achieve this functionality I use glob pattern.

code of my example:

visitor interface realization:

class MyFileFindVisitor extends SimpleFileVisitor<Path> {
    private PathMatcher matcher;
    public MyFileFindVisitor(String pattern){
        try {
            matcher = FileSystems.getDefault().getPathMatcher(pattern);
        } catch(IllegalArgumentException iae) {
            System.err.println("Invalid pattern; did you forget to prefix \"glob:\"? (as in glob:*.java)");
            System.exit(1);
        }
    }
    public FileVisitResult visitFile(Path path, BasicFileAttributes fileAttributes){
        find(path);
        return FileVisitResult.CONTINUE;
    }
    private void find(Path path) {
        Path name = path.getFileName();
        if(matcher.matches(name))
            System.out.println("Matching file:" + path.getFileName());
    }
    public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes fileAttributes){
        find(path);
        return FileVisitResult.CONTINUE;
    }
}

main method:

public static void main(String[] args) {
        Path startPath = Paths.get("E:\\folder");
        String pattern = "glob:*";
        try {
            Files.walkFileTree(startPath, new MyFileFindVisitor(pattern));
            System.out.println("File search completed!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

This variant of main method works properly but if I change:

Path startPath = Paths.get("E:\\folder");

with

Path startPath = Paths.get("E:\\"); 

I see following stacktrace:

Exception in thread "main" java.lang.NullPointerException
    at sun.nio.fs.WindowsFileSystem$2.matches(WindowsFileSystem.java:312)
    at io.nio.MyFileFindVisitor.find(FileTreeWalkFind.java:29)
    at io.nio.MyFileFindVisitor.preVisitDirectory(FileTreeWalkFind.java:33)
    at io.nio.MyFileFindVisitor.preVisitDirectory(FileTreeWalkFind.java:13)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:192)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:69)
    at java.nio.file.Files.walkFileTree(Files.java:2600)
    at java.nio.file.Files.walkFileTree(Files.java:2633)
    at io.nio.FileTreeWalkFind.main(FileTreeWalkFind.java:42)

I don't the cause of this problem.

How to solve it?


Solution

  • The reason you are getting a null pointer exception is because when your visitor tests the very first path (E:\), there is no actual file name to test - this is a volume root directory. From the JDK Docs:

    Path getFileName()
    
    Returns the name of the file or directory denoted by this path as a Path object. The file name is the farthest element from the root in the directory hierarchy.
    
    Returns:
        a path representing the name of the file or directory, or null if this path has zero elements
    

    "Elements", in this case, means directory elements in the name. 'E:\' has no directory elements, as it is the root for the volume.

    You should not assume that filename is always going to be not null.

    private void find(Path path) {          
        Path name = path.getFileName();
        if (name != null) {
            if(matcher.matches(name)) {
                System.out.println("Matching file:" + path.getFileName());
            }
        }
    }
    

    Other things that you might need to watch for when walking Windows file systems include:

    • System protected directories, such as the recycle bins, that your walker may not be able to descend into
    • NTFS Junction points that might result in recursive directories that loop back on themselves, resulting in your code looping until you run out of heap or stack