java glob paths_Files.walkFileTree遍历目录文件

本文详细介绍了Java NIO中的Files.walkFileTree方法,用于遍历目录和文件。通过设置不同的参数和FileVisitor,可以实现深度遍历、文件过滤等功能。文章还提供了多个示例,演示了如何查找特定扩展名的文件、遍历单层目录以及复制文件到新目录的操作。
摘要由CSDN通过智能技术生成

Files.walkFileTree遍历目录文件

java.nio.file.Files.walkFileTree是JDK7新增的静态工具方法。

Files.walkFileTree的原理介绍

static Path walkFileTree(Path start, Set options, int maxDepth, FileVisitor super Path> visitor) throws IOException;

static Path walkFileTree(Path start, FileVisitor super Path> visitor) throws IOException;

参数列表:

java.nio.file.Path start 遍历的起始路径

Set options 遍历选项

int maxDepth 遍历深度

java.nio.file.FileVisitor super Path> visitor 遍历过程中的行为控制器

遍历行为控制器FileVisitor

接口java.nio.file.FileVisitor包含四个方法,涉及到遍历过程中的几个重要的步骤节点。一般实际中使用SimpleFileVisitor简化操作。

public interface FileVisitor {

FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)

throws IOException;

FileVisitResult visitFile(T file, BasicFileAttributes attrs)

throws IOException;

FileVisitResult visitFileFailed(T file, IOException exc)

throws IOException;

FileVisitResult postVisitDirectory(T dir, IOException exc)

throws IOException;

}

preVisitDirectory 访问一个目录,在进入之前调用。

postVisitDirectory 一个目录的所有节点都被访问后调用。遍历时跳过同级目录或有错误发生,Exception会传递给这个方法

visitFile 文件被访问时被调用。该文件的文件属性被传递给这个方法

visitFileFailed 当文件不能被访问时,此方法被调用。Exception被传递给这个方法。

遍历行为结果 FileVisitResult

public enum FileVisitResult {

CONTINUE,

TERMINATE,

SKIP_SUBTREE,

SKIP_SIBLINGS;

}

CONTINUE 继续遍历

SKIP_SIBLINGS 继续遍历,但忽略当前节点的所有兄弟节点直接返回上一层继续遍历

SKIP_SUBTREE 继续遍历,但是忽略子目录,但是子文件还是会访问

TERMINATE 终止遍历

查找指定文件

使用java.nio.file.Path提供的startsWith、endsWith等方法,需要特别注意的是:匹配的是路径节点的完整内容,而不是字符串。

例如: /usr/web/bbf.jar

Path path = Paths.get("/usr/web/bbf.jar");

path.endsWith("bbf.jar"); // true

path.endsWith(".jar"); // false

使用PathMatcher

@Test

public void visitFile2() throws IOException {

// 查找java和txt文件

String glob = "glob:**/*.{java,txt}";

String path = "D:\\work_java\\bbf\\CORE";

final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(glob);

Files.walkFileTree(Paths.get(path), new SimpleFileVisitor() {

@Override

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)

throws IOException {

if (pathMatcher.matches(file)) {

System.out.println(file);

}

return FileVisitResult.CONTINUE;

}

});

}

getPathMatcher方法的参数语法:规则:模式,其中规则支持两种模式glob和regex。

全局规则glob

使用类似于正则表达式但语法更简单的模式,匹配路径的字符串。

glob:*.java 匹配以java结尾的文件

glob:*.* 匹配包含'.'的文件

glob:*.{java,class} 匹配以java或class结尾的文件

glob:foo.? 匹配以foo开头且一个字符扩展名的文件

glob:/home/*/* 在unix平台上匹配,例如/home/gus/data等

glob:/home/** 在unix平台上匹配,例如/home/gus,/home/gus/data

glob:c:\\\\* 在windows平台上匹配,例如c:foo,c:bar,注意字符串转义

规则说明

* 匹配零个或多个字符与名称组件,不跨越目录

** 匹配零个或多个字符与名称组件,跨越目录(含子目录)

? 匹配一个字符的字符与名称组件

\ 转义字符,例如\{表示匹配左花括号

[] 匹配方括号表达式中的范围,连字符(-)可指定范围。例如[ABC]匹配"A"、"B"和"C";[a-z]匹配从"a"到"z";[abce-g]匹配"a"、"b"、"c"、"e"、"f"、"g";

[!...]匹配范围之外的字符与名称组件,例如[!a-c]匹配除"a"、"b"、"c"之外的任意字符

{}匹配组中的任意子模式,多个子模式用","分隔,不能嵌套。

正则规则regex

使用java.util.regex.Pattern支持的正则表达式。

示例

获取指定扩展名的文件

以下测试用例,目的都是获取指定目录下的.properties和.html文件。

/**

* 递归遍历,字符串判断

*

* @throws IOException IO异常

*/

@Test

public void visitFile1() throws IOException {

String path = "D:\\work_java\\hty\\HTY_CORE";

Files.walkFileTree(Paths.get(path), new SimpleFileVisitor() {

@Override

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)

throws IOException {

String pathStr = file.toString();

if (pathStr.endsWith("properties") || pathStr.endsWith("html")) {

System.out.println(file);

}

return FileVisitResult.CONTINUE;

}

});

}

/**

* 递归遍历,glob模式

*

* @throws IOException IO异常

*/

@Test

public void visitFile2() throws IOException {

String glob = "glob:**/*.{properties,html}";

String path = "D:\\work_java\\hty\\HTY_CORE";

final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(glob);

Files.walkFileTree(Paths.get(path), new SimpleFileVisitor() {

@Override

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)

throws IOException {

if (pathMatcher.matches(file)) {

System.out.println(file);

}

return FileVisitResult.CONTINUE;

}

});

}

/**

* 递归遍历,正则模式

*

* @throws IOException IO异常

*/

@Test

public void visitFile3() throws IOException {

// (?i)忽略大小写,(?:)标记该匹配组不应被捕获

String reg = "regex:.*\\.(?i)(?:properties|html)";

String path = "D:\\work_java\\hty\\HTY_CORE";

final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(reg);

Files.walkFileTree(Paths.get(path), new SimpleFileVisitor() {

@Override

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)

throws IOException {

if (pathMatcher.matches(file)) {

System.out.println(file);

}

return FileVisitResult.CONTINUE;

}

});

}

查找指定文件

/**

* 查找指定文件

*

* @throws IOException IO异常

*/

@Test

public void visitFile() throws IOException {

String path = "D:\\work_java\\hty\\HTY_CORE\\src";

Files.walkFileTree(Paths.get(path), new SimpleFileVisitor() {

@Override

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)

throws IOException {

// 使用endsWith,必须是路径中的一段,而不是几个字符

if (file.endsWith("log.java")) {

System.out.println(file);

// 找到文件,终止操作

return FileVisitResult.TERMINATE;

}

return FileVisitResult.CONTINUE;

}

});

}

遍历单层目录

使用DirectoryStream会获取指定目录下的目录和文件。可以使用newDirectoryStream的第二个参数进行筛选,glob语法。

/**

* 遍历单层目录

*

* @throws IOException IO异常

*/

@Test

public void dir() throws IOException {

Path source = Paths.get("D:\\work_java\\hty\\HTY_CORE\\src\\main\\resources");

try (DirectoryStream stream = Files.newDirectoryStream(source, "*.xml")) {

Iterator ite = stream.iterator();

while (ite.hasNext()) {

Path pp = ite.next();

System.out.println(pp.getFileName());

}

}

}

复制文件到新目录

/**

* 递归复制

*

* @throws IOException IO异常

*/

@Test

public void copyAll() throws IOException {

Path source = Paths.get("D:\\work_java\\hty\\HTY_CORE\\src");

Path target = Paths.get("D:\\temp\\core");

// 源文件夹非目录

if (!Files.isDirectory(source)) {

throw new IllegalArgumentException("源文件夹错误");

}

// 源路径的层级数

int sourcePart = source.getNameCount();

Files.walkFileTree(source, new SimpleFileVisitor() {

@Override

public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)

throws IOException {

// 在目标文件夹中创建dir对应的子文件夹

Path subDir;

if (dir.compareTo(source) == 0) {

subDir = target;

} else {

// 获取相对原路径的路径名,然后组合到target上

subDir = target.resolve(dir.subpath(sourcePart, dir.getNameCount()));

}

Files.createDirectories(subDir);

return FileVisitResult.CONTINUE;

}

@Override

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {

Files.copy(file, target.resolve(file.subpath(sourcePart, file.getNameCount())),

StandardCopyOption.REPLACE_EXISTING);

return FileVisitResult.CONTINUE;

}

});

System.out.println("复制完毕");

}

文件和流的复制

/**

* 流复制到文件

*

* @throws IOException IO异常

*/

@Test

public void copy1() throws IOException {

Path source = Paths.get("D:\\work_java\\hty\\HTY_CORE\\src\\main\\resources\\ehcache.xml");

Path target = Paths.get("D:\\temp\\");

if (!Files.exists(target)) {

Files.createDirectories(target);

}

Path targetFile = target.resolve(source.getFileName());

try (InputStream fs = FileUtils.openInputStream(source.toFile())) {

Files.copy(fs, targetFile, StandardCopyOption.REPLACE_EXISTING);

}

}

/**

* 文件复制到流

*

* @throws IOException IO异常

*/

@Test

public void copy2() throws IOException {

Path source = Paths.get("D:\\work_java\\hty\\HTY_CORE\\src\\main\\resources\\ehcache.xml");

Path target = Paths.get("D:\\temp\\core");

Path targetFile = target.resolve(source.getFileName());

if (!Files.exists(target)) {

Files.createDirectories(target);

}

try (OutputStream fs = FileUtils.openOutputStream(targetFile.toFile());

OutputStream out = new BufferedOutputStream(fs)) {

Files.copy(source, out);

}

}

Path与File的转换

/**

* Path与File的转换

*/

@Test

public void testPath() {

File file = new File("D:\\work_java\\hty\\HTY_CORE");

System.out.println(file.toURI());

System.out.println(file.getAbsolutePath());

System.out.println(file.getName());

System.out.println("-------");

Path path = Paths.get(file.toURI());

System.out.println(path.toUri());

System.out.println(path.toAbsolutePath());

System.out.println(path.getFileName());

System.out.println("-------");

File f = path.toFile();

System.out.println(f.getAbsolutePath());

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值