From 583b7cbe47869f35a72fccbdc57ef88828748c8c Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 16 Nov 2020 18:02:27 +0800 Subject: [PATCH] add visitor --- CHANGELOG.md | 4 +- .../java/cn/hutool/core/io/file/PathUtil.java | 71 ++++++++++++------- .../core/io/file/visitor/CopyVisitor.java | 46 ++++++++++++ .../core/io/file/visitor/DelVisitor.java | 35 +++++++++ .../core/io/file/visitor/package-info.java | 7 ++ .../cn/hutool/core/io/file/PathUtilTest.java | 9 +++ 6 files changed, 146 insertions(+), 26 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/io/file/visitor/package-info.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ca3fa474..085a3ea41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,11 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.1 (2020-11-15) +# 5.5.1 (2020-11-16) ### 新特性 +* 【core 】 增加CopyVisitor和DelVisitor + ### Bug修复 * 【core 】 修复在Linux下FileUtil.move失败问题(issue#I254Y3@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index 567532dc9..50ee10ca9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -2,6 +2,8 @@ package cn.hutool.core.io.file; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.file.visitor.CopyVisitor; +import cn.hutool.core.io.file.visitor.DelVisitor; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.CharsetUtil; @@ -128,24 +130,7 @@ public class PathUtil { try { if (isDirectory(path)) { - Files.walkFileTree(path, new SimpleFileVisitor() { - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { - if (e == null) { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } else { - throw e; - } - } - }); + Files.walkFileTree(path, DelVisitor.INSTANCE); } else { Files.delete(path); } @@ -158,7 +143,7 @@ public class PathUtil { /** * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件 * - * @param src 源文件路径 + * @param src 源文件路径,如果为目录只在目标中创建新目录 * @param dest 目标文件或目录,如果为目录使用与源文件相同的文件名 * @param options {@link StandardCopyOption} * @return Path @@ -171,25 +156,61 @@ public class PathUtil { /** * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件 * - * @param src 源文件路径 - * @param dest 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @param src 源文件路径,如果为目录只在目标中创建新目录 + * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 * @param options {@link StandardCopyOption} * @return Path * @throws IORuntimeException IO异常 * @since 5.4.1 */ - public static Path copyFile(Path src, Path dest, CopyOption... options) throws IORuntimeException { + public static Path copyFile(Path src, Path target, CopyOption... options) throws IORuntimeException { Assert.notNull(src, "Source File is null !"); - Assert.notNull(dest, "Destination File or directiory is null !"); + Assert.notNull(target, "Destination File or directiory is null !"); - Path destPath = isDirectory(dest) ? dest.resolve(src.getFileName()) : dest; + final Path targetPath = isDirectory(target) ? target.resolve(src.getFileName()) : target; try { - return Files.copy(src, destPath, options); + return Files.copy(src, targetPath, options); } catch (IOException e) { throw new IORuntimeException(e); } } + /** + * 拷贝文件或目录 + * + * @param src 源文件路径,如果为目录只在目标中创建新目录 + * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @param options {@link StandardCopyOption} + * @return Path + * @throws IORuntimeException IO异常 + * @since 5.5.1 + */ + public static Path copy(Path src, Path target, CopyOption... options) throws IORuntimeException { + if(isFile(src, false)){ + return copyFile(src, target, options); + } + return copyContent(src, target.resolve(src.getFileName()), options); + } + + /** + * 拷贝目录下的所有文件或目录到目标目录中 + * + * @param src 源文件路径,如果为目录只在目标中创建新目录 + * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @param options {@link StandardCopyOption} + * @return Path + * @throws IORuntimeException IO异常 + * @since 5.5.1 + */ + public static Path copyContent(Path src, Path target, CopyOption... options) throws IORuntimeException { + try { + Files.walkFileTree(src, new CopyVisitor(src, target)); + } catch (IOException e) { + throw new IORuntimeException(e); + } + return target; + } + /** * 判断是否为目录,如果file为null,则返回false
* 此方法不会追踪到软链对应的真实地址,即软链被当作文件 diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java new file mode 100644 index 000000000..e633e8ac8 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java @@ -0,0 +1,46 @@ +package cn.hutool.core.io.file.visitor; + +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +/** + * 文件拷贝的FileVisitor实现,用于递归遍历拷贝目录 + * + * @author looly + * @since 5.5.1 + */ +public class CopyVisitor extends SimpleFileVisitor { + + final Path source; + final Path target; + + public CopyVisitor(Path source, Path target) { + this.source = source; + this.target = target; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException { + final Path targetDir = target.resolve(source.relativize(dir)); + try { + Files.copy(dir, targetDir); + } catch (FileAlreadyExistsException e) { + if (!Files.isDirectory(targetDir)) + throw e; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.copy(file, target.resolve(source.relativize(file))); + return FileVisitResult.CONTINUE; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java new file mode 100644 index 000000000..1121373c0 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java @@ -0,0 +1,35 @@ +package cn.hutool.core.io.file.visitor; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +/** + * 删除操作的FileVisitor实现,用于递归遍历删除文件夹 + * + * @author looly + * @since 5.5.1 + */ +public class DelVisitor extends SimpleFileVisitor { + + public static DelVisitor INSTANCE = new DelVisitor(); + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { + if (e == null) { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } else { + throw e; + } + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/package-info.java b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/package-info.java new file mode 100644 index 000000000..dfc045675 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/package-info.java @@ -0,0 +1,7 @@ +/** + * FileVisitor功能性实现,包括递归删除、拷贝等 + * + * @author looly + * + */ +package cn.hutool.core.io.file.visitor; \ No newline at end of file diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java index 2d5b14dfd..b547d7e96 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java @@ -19,6 +19,15 @@ public class PathUtilTest { ); } + @Test + @Ignore + public void copyTest(){ + PathUtil.copy( + Paths.get("d:/Red2_LYY"), + Paths.get("d:/test/") + ); + } + @Test @Ignore public void moveTest(){