The Files.find API is available since Java 8. It searches or finds files from a file tree quickly.

In the old days, we always use an error-prone recursive loop to walk a file tree. This Java 8 Files.find can save you a lot of time.

1. Files.find() Signature

Review the Files.find() signature.

Files.java

public static Stream<Path> find(Path start,
                                int maxDepth,
                                BiPredicate<Path, BasicFileAttributes> matcher,
                                FileVisitOption... options)
        throws IOException
  • The path, starting file or folder.
  • The maxDepth defined the maximum number of directory levels to search. If we put 1, which means the search for top-level or root folder only, ignore all its subfolders; If we want to search for all folder levels, put Integer.MAX_VALUE.
  • The BiPredicate<Path, BasicFileAttributes> is for condition checking or filtering.
  • The FileVisitOption tells if we want to follow symbolic links, default is no. We can put FileVisitOption.FOLLOW_LINKS to follow symbolic links.

2. Find files by filename

This example uses Files.find() to find files that matched filename google.png, starting from the folder C:\\test, and included all levels of its subfolders.

FileFindExample1.java

package com.favtuts.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileFindExample1 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\test");
        List<Path> result = findByFileName(path, "google.png");
        result.forEach(x -> System.out.println(x));

    }

    public static List<Path> findByFileName(Path path, String fileName)
            throws IOException {

        List<Path> result;
        try (Stream<Path> pathStream = Files.find(path,
                Integer.MAX_VALUE,
                (p, basicFileAttributes) ->
                        p.getFileName().toString().equalsIgnoreCase(fileName))
        ) {
            result = pathStream.collect(Collectors.toList());
        }
        return result;

    }

}

We also can use Files APIs to check the path further.

FileFindExample1.java

  try (Stream<Path> pathStream = Files.find(path,
         Integer.MAX_VALUE,
         (p, basicFileAttributes) ->{
             // if directory or no-read permission, ignore
             if(Files.isDirectory(p) || !Files.isReadable(p)){
                 return false;
             }
             return p.getFileName().toString().equalsIgnoreCase(fileName);
         })
 )

3. Find files by file size

This example uses Files.find() to find files containing file size greater or equals 100MB.

FileFindExample2.java

package com.favtuts.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileFindExample2 {

    public static void main(String[] args) throws IOException {

        Path path = Paths.get("C:\\Users\\favtuts\\Downloads");

        long fileSize = 1024 * 1024 * 100; // 100M

        List<Path> result = findByFileSize(path, fileSize);
        for (Path p : result) {
            System.out.println(String.format("%-40s [fileSize]: %,d", p, Files.size(p)));
        }

    }

    public static List<Path> findByFileSize(Path path, long fileSize)
            throws IOException {

        List<Path> result;
        try (Stream<Path> pathStream = Files.find(path,
                Integer.MAX_VALUE,
                (p, basicFileAttributes) -> {
                    try {
                        if (Files.isDirectory(p)) {   // ignore directory
                            return false;
                        }
                        return Files.size(p) >= fileSize;
                    } catch (IOException e) {
                        System.err.println("Unable to get the file size of path : " + path);
                    }
                    return false;
                }

        )) {
            result = pathStream.collect(Collectors.toList());
        }
        return result;

    }

}

Output samples.


C:\Users\favtuts\Downloads\hello.mp4 [fileSize]: 4,796,543,886
C:\Users\favtuts\Downloads\java.mp4.bk [fileSize]: 5,502,785,778
C:\Users\favtuts\Downloads\ubuntu-20.04.1-desktop-amd64.iso [fileSize]: 2,785,017,856

#...

4. Find files by last modified time

This example uses File.find() to find files containing last modified time equals or after yesterday.

FileFindExample3.java

package com.favtuts.io.api;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileFindExample3 {

    private static DateTimeFormatter DATE_FORMATTER
            = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");

    public static void main(String[] args) throws IOException {

        // find files, LastModifiedTime from yesterday and above
        List<Path> result = findByLastModifiedTime(
                Paths.get("C:\\test"),
                Instant.now().minus(1, ChronoUnit.DAYS));

        for (Path p : result) {

            // formatting...
            BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class);
            FileTime time = attrs.lastModifiedTime();
            LocalDateTime localDateTime = time.toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();

            System.out.println(String.format("%-40s [%s]", p, localDateTime.format(DATE_FORMATTER)));
        }

    }

    public static List<Path> findByLastModifiedTime(Path path, Instant instant)
            throws IOException {

        List<Path> result;
        try (Stream<Path> pathStream = Files.find(path,
                Integer.MAX_VALUE,
                (p, basicFileAttributes) -> {

                    if(Files.isDirectory(p) || !Files.isReadable(p)){
                        return false;
                    }

                    FileTime fileTime = basicFileAttributes.lastModifiedTime();
                    // negative if less, positive if greater
                    // 1 means fileTime equals or after the provided instant argument
                    // -1 means fileTime before the provided instant argument
                    int i = fileTime.toInstant().compareTo(instant);
                    return i > 0;
                }

        )) {
            result = pathStream.collect(Collectors.toList());
        }
        return result;

    }

}

Output samples and assume today is 02/12/2020

C:\test\a.txt                          [02/12/2020 13:01:20]
C:\test\b.txt                          [01/12/2020 12:11:21]

#...

Download Source Code

$ git clone https://github.com/favtuts/java-core-tutorials-examples

$ cd java-io

References

Leave a Reply

Your email address will not be published. Required fields are marked *