我有这个函数以递归方式打印目录中的所有文件的名称.问题是我的代码非常慢,因为它必须在每次迭代时访问远程网络设备.
我的计划是先递归加载目录中的所有文件,然后再使用正则表达式遍历所有文件,过滤掉我不想要的所有文件.有人有更好的建议吗?
public static printFnames(String sDir){
File[] faFiles = new File(sDir).listFiles();
for(File file: faFiles){
if(file.getName().matches("^(.*?)")){
System.out.println(file.getAbsolutePath());
}
if(file.isDirectory()){
printFnames(file.getAbsolutePath());
}
}
}
Run Code Online (Sandbox Code Playgroud)
这只是稍后的一个测试,我不打算使用这样的代码,而是我要将每个匹配高级正则表达式的文件的路径和修改日期添加到数组中.
ska*_*man 130
假设这是实际的生产代码,你会写,那么我建议使用解决这样的事情这已经得到解决- 阿帕奇百科全书IO,具体FileUtils.listFiles().它处理嵌套目录,过滤器(基于名称,修改时间等).
例如,对于你的正则表达式:
Collection files = FileUtils.listFiles(
dir,
new RegexFileFilter("^(.*?)"),
DirectoryFileFilter.DIRECTORY
);
Run Code Online (Sandbox Code Playgroud)
这将递归搜索与^(.*?)正则表达式匹配的文件,并将结果作为集合返回.
值得注意的是,这并不比滚动自己的代码快,它做同样的事情 - 用Java搜索文件系统的速度很慢.不同的是,Apache Commons版本中没有任何错误.
Boh*_*ian 59
在Java 8,它是通过1衬垫Files.find()与一个任意大的深度(例如999)和BasicFileAttributes的isRegularFile()
public static printFnames(String sDir) {
Files.find(Paths.get(sDir), 999, (p, bfa) -> bfa.isRegularFile()).forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)
要添加更多过滤,请增强lambda,例如在过去24小时内修改的所有jpg文件:
(p, bfa) -> bfa.isRegularFile()
&& p.getFileName().toString().matches(".*\\.jpg")
&& bfa.lastModifiedTime().toMillis() > System.currentMillis() - 86400000
Run Code Online (Sandbox Code Playgroud)
Dan*_*Dan 26
这是一个非常简单的递归方法,用于从给定的根获取所有文件.
它使用Java 7 NIO Path类.
private List<String> getFileNames(List<String> fileNames, Path dir) {
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path path : stream) {
if(path.toFile().isDirectory()) {
getFileNames(fileNames, path);
} else {
fileNames.add(path.toAbsolutePath().toString());
System.out.println(path.getFileName());
}
}
} catch(IOException e) {
e.printStackTrace();
}
return fileNames;
}
Run Code Online (Sandbox Code Playgroud)
jbo*_*boi 18
使用Java 7,通过Paths和Files功能引入了更快的通过目录树行走的方式.它们比"旧" File方式快得多.
这将是通过正则表达式遍历和检查路径名称的代码:
public final void test() throws IOException, InterruptedException {
final Path rootDir = Paths.get("path to your directory where the walk starts");
// Walk thru mainDir directory
Files.walkFileTree(rootDir, new FileVisitor<Path>() {
// First (minor) speed up. Compile regular expression pattern only one time.
private Pattern pattern = Pattern.compile("^(.*?)");
@Override
public FileVisitResult preVisitDirectory(Path path,
BasicFileAttributes atts) throws IOException {
boolean matches = pattern.matcher(path.toString()).matches();
// TODO: Put here your business logic when matches equals true/false
return (matches)? FileVisitResult.CONTINUE:FileVisitResult.SKIP_SUBTREE;
}
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes mainAtts)
throws IOException {
boolean matches = pattern.matcher(path.toString()).matches();
// TODO: Put here your business logic when matches equals true/false
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path path,
IOException exc) throws IOException {
// TODO Auto-generated method stub
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path path, IOException exc)
throws IOException {
exc.printStackTrace();
// If the root directory has failed it makes no sense to continue
return path.equals(rootDir)? FileVisitResult.TERMINATE:FileVisitResult.CONTINUE;
}
});
}
Run Code Online (Sandbox Code Playgroud)
Rea*_*wTo 13
使用Java 7 NIO获取目录内容的快捷方法:
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.FileSystems;
import java.nio.file.Path;
...
Path dir = FileSystems.getDefault().getPath( filePath );
DirectoryStream<Path> stream = Files.newDirectoryStream( dir );
for (Path path : stream) {
System.out.println( path.getFileName() );
}
stream.close();
Run Code Online (Sandbox Code Playgroud)
Kev*_*Day 12
Java用于读取文件系统文件夹内容的界面性能不是很高(正如您所发现的那样).JDK 7通过一个全新的接口来解决这个问题,它应该为这些类型的操作带来本机级别的性能.
核心问题是Java为每个文件进行本机系统调用.在低延迟接口上,这不是什么大不了的事 - 但在具有中等延迟的网络上,它真的会增加.如果您对上面的算法进行了分析,您会发现大部分时间花在了烦人的isDirectory()调用上 - 这是因为您每次调用isDirectory()都会产生一次往返.大多数现代操作系统可以在最初请求文件/文件夹列表时提供此类信息(而不是查询每个文件路径的属性).
如果您不能等待JDK7,那么解决此延迟的一种策略是使用多线程并使用具有最多线程数的ExecutorService来执行递归.它不是很好(你必须处理输出数据结构的锁定),但它比这个单线程更快.
在您关于此类事情的所有讨论中,我强烈建议您使用本机代码(甚至是执行大致相同操作的命令行脚本)进行比较.说遍历网络结构需要一个小时并不是真的意味着那么多.告诉我们你可以在7秒内完成原生,但是用Java需要一个小时才会引起人们的注意.
这将工作得很好...和它的递归
File root = new File("ROOT PATH");
for ( File file : root.listFiles())
{
getFilesRecursive(file);
}
private static void getFilesRecursive(File pFile)
{
for(File files : pFile.listFiles())
{
if(files.isDirectory())
{
getFilesRecursive(files);
}
else
{
// do your thing
// you can either save in HashMap and use it as
// per your requirement
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
163576 次 |
| 最近记录: |