Java DirectoryStream.Filter 示例,用于列出基于特定日期/时间的文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21733390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DirectoryStream.Filter example for listing files that based on certain date/time
提问by Ashley
I am trying to investigate a DirecoryStream.Filter
example for newDirectoryStream
where I can achieve to list all files under a directory(and all its sub directories) that are older than 60 days, as an example.
我正在尝试研究一个DirecoryStream.Filter
示例newDirectoryStream
,我可以在其中列出目录(及其所有子目录)下超过 60 天的所有文件,例如。
DirectoryStream<Path> dirS = Files.newDirectoryStream(Paths.get("C:/myRootDirectory"), <DirectoryStream.filter>);
for (Path entry: dirS) {
System.out.println(entry.toString());
}
In the code above, what should be the DirectoryStream.filter
?
It will be a great help as I am in a project where I am trying to delete files older than a certain timestamp and pre-java 1.7 File.listFiles()
just hangs.
在上面的代码中,应该是DirectoryStream.filter
什么?
这将是一个很大的帮助,因为我在一个项目中,我试图删除早于某个时间戳的文件并且 java 1.7 之前的版本File.listFiles()
只是挂起。
Could Files.walkFileTree()
provide an option?
可以Files.walkFileTree()
提供一个选项吗?
采纳答案by PopoFibo
If I get this right, you have 2 situations:
如果我做对了,你有两种情况:
- Create a custom
filter
to select files older than 60 days - Traverse through subdirectories (the entire
FileTree
) and gather your information
- 创建自定义
filter
以选择超过 60 天的文件 - 遍历子目录(整个
FileTree
)并收集您的信息
The custom filter is easier to implement with conditions of 60 days implemented using Calendar
class:
使用Calendar
类实现的 60 天条件更容易实现自定义过滤器:
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {BasicFileAttributes attr = Files.readAttributes(entry,BasicFileAttributes.class);
FileTime creationTime = attr.creationTime();
Calendar cal = Calendar.getInstance();
int days = cal.fieldDifference(new Date(creationTime.toMillis()),Calendar.DAY_OF_YEAR);
return (Math.abs(days) > 60);
}
};
The normal execution would only look for the files in the root directory. To look for subdirectory, your guess of using walkFileTree()
is right.
正常执行只会在根目录中查找文件。要查找子目录,您使用的猜测walkFileTree()
是正确的。
However, this requires an implementation of the FileVisitor
interface, a simple implementation of which luckily is bundled with 7 - SimpleFileVisitor
.
但是,这需要FileVisitor
接口的实现,幸运的是,它的简单实现与 7 - 捆绑在一起SimpleFileVisitor
。
To traverse through the subdirectories, you can choose to override a directory specific method - I have used preVisitDirectory
of SimpleFileVisitor
here:
要遍历子目录,您可以选择覆盖特定于目录的方法 - 我preVisitDirectory
在SimpleFileVisitor
这里使用过:
Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path file,
BasicFileAttributes attrs) {
Since preVisitDirectory
will be custom made to return FileVisitResult.CONTINUE;
in case you don't have any additional restrictions, we would leverage preVisitDirectory
method to iterate through our directory 1 at a time while applying the filter.
由于preVisitDirectory
将是定制的return FileVisitResult.CONTINUE;
,以防您没有任何其他限制,我们将利用preVisitDirectory
方法在应用过滤器时一次迭代我们的目录 1。
Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path file,
BasicFileAttributes attrs) {
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
BasicFileAttributes attr = Files.readAttributes(entry,
BasicFileAttributes.class);
FileTime creationTime = attr.creationTime();
Calendar cal = Calendar.getInstance();
int days = cal.fieldDifference(
new Date(creationTime.toMillis()),
Calendar.DAY_OF_YEAR);
return (Math.abs(days) > 60);
}
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
file, filter)) {
for (Path path : stream) {
System.out.println(path.toString());
}
} catch (IOException ex) {
ex.printStackTrace();
}
return FileVisitResult.CONTINUE;
}
});
This would give you the files from the entire directory and subdirectory structures for the required filter criteria, complete main method below:
这将为您提供所需过滤条件的整个目录和子目录结构中的文件,完整的主要方法如下:
public static void main(String[] args) throws IOException {
Path dirs = Paths.get("C:/");
Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path file,
BasicFileAttributes attrs) {
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
BasicFileAttributes attr = Files.readAttributes(entry,
BasicFileAttributes.class);
FileTime creationTime = attr.creationTime();
Calendar cal = Calendar.getInstance();
int days = cal.fieldDifference(
new Date(creationTime.toMillis()),
Calendar.DAY_OF_YEAR);
return (Math.abs(days) > 60);
}
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
file, filter)) {
for (Path path : stream) {
System.out.println(path.toString());
}
} catch (IOException ex) {
ex.printStackTrace();
}
return FileVisitResult.CONTINUE;
}
});
}
回答by Sotirios Delimanolis
Simply create a new DirectoryStream.Filter
instance that returns true
if the given Path
object is older than 60 days.
只需创建一个新DirectoryStream.Filter
实例,true
如果给定Path
对象超过 60 天,则返回该实例。
DirectoryStream<Path> dirStream = Files.newDirectoryStream(Paths.get("/some/path"), new Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
FileTime fileTime = Files.getLastModifiedTime(entry);
long millis = fileTime.to(TimeUnit.MILLISECONDS);
Calendar today = Calendar.getInstance();
// L is necessary for the result to correctly be calculated as a long
return today.getTimeInMillis() > millis + (60L * 24 * 60 * 60 * 1000);
}
});
Note that this will only give you the files inside the root of the specified directory Path
, ie. the Path
argument passed to newDirectoryStream(..)
.
请注意,这只会为您提供指定目录根目录下的文件Path
,即。该Path
参数传递给newDirectoryStream(..)
。
If you want all files in sub directories as well, Files.walkFileTree(..)
is probably easier to use. You'll just have to implement a FileVisitor
that stores a List
or Set
of Path
objects that you collect along the way using the same logic as the Filter
above.
如果您还想要子目录中的所有文件,Files.walkFileTree(..)
则可能更容易使用。您只需要使用与上述相同的逻辑来实现FileVisitor
存储沿途收集的一个List
或Set
多个Path
对象的Filter
。