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
maxDepthdefined the maximum number of directory levels to search. If we put1, which means the search for top-level or root folder only, ignore all its subfolders; If we want to search for all folder levels, putInteger.MAX_VALUE. - The
BiPredicate<Path, BasicFileAttributes>is for condition checking or filtering. - The
FileVisitOptiontells if we want to follow symbolic links, default is no. We can putFileVisitOption.FOLLOW_LINKSto 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