Path.endswith() 的是 Path 不是文件名后缀 | LIXI.FUN
0%

Path.endswith() 的是 Path 不是文件名后缀

假设有这样一个需求,删除某一个目录下的 “.json” 结尾的,修改时间在 x 分钟之前的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Solution {

public static void main(String[] args) {
delete(Path.of("/home/lixifun/log"), ".json", 30, TimeUnit.MINUTES);
}

private static void delete(Path dir, String suffix, int time, TimeUnit timeUnit) {

Instant timeNodeToDelete = Instant.now().minusMillis(timeUnit.toMillis(time));

DirectoryStream.Filter<Path> filter = file -> {
Instant fileLastModTime = Files.getLastModifiedTime(file).toInstant();

// 问题就出现在下面两句了
// 注释掉的是不正确的
// return file.endsWith(suffix)
// && fileLastModTime.isBefore(timeNodeToDelete);

// 这个是正确的
return file.toString().endsWith(suffix)
&& fileLastModTime.isBefore(timeNodeToDelete);

};

try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dir, filter)) {
for (Path file : dirStream) {
Files.delete(file);
}
} catch (IOException e) {
e.printStackTrace();
}
}

主要问题就在 Path.endswith() 不是用来匹配后缀的,是用来匹配 Path 的,仅仅一个后缀 不能 表示一个 Path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class PathTest {

public static void main(String[] args) {
Path aLog = Path.of("/home/lixifun/log/log1.json");

System.out.println(aLog.endsWith("json")); // false
System.out.println(aLog.endsWith(".json")); // false
System.out.println(aLog.endsWith("1.json")); // false
System.out.println(aLog.endsWith("log1.json")); // true
System.out.println(aLog.endsWith("/log1.json")); // false
System.out.println(aLog.endsWith("log/log1.json")); // true

}
}

通过示例可以看出只有在完全匹配文件名或某个相对路径(不带.)时才匹配。

通过查看源码 Path.endswith(String) 调用的是 Path.endswith(Path) 也就是说 String 类型仅仅是作为字面量来表示某个 Path 的,实际匹配的是 Path

觉得有收获就鼓励下作者吧