diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java index 7c41eaf77..ad6b417e9 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java @@ -19,6 +19,8 @@ import org.dromara.hutool.core.func.SerFunction; import org.dromara.hutool.core.io.BomReader; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; +import org.dromara.hutool.core.io.resource.FileResource; +import org.dromara.hutool.core.io.resource.Resource; import org.dromara.hutool.core.io.resource.ResourceUtil; import org.dromara.hutool.core.io.stream.BOMInputStream; import org.dromara.hutool.core.io.unit.DataSizeUtil; @@ -214,7 +216,7 @@ public class FileUtil extends PathUtil { * * 此方法与{@link #loopFiles(File, FileFilter)}不同的是,处理目录判断,可减少无效目录的遍历。 * - * @param file 文件或目录,文件直接处理 + * @param file 文件或目录,文件直接处理 * @param predicate 文件处理器,只会处理文件 * @since 5.5.2 */ @@ -911,6 +913,31 @@ public class FileUtil extends PathUtil { } // endregion + // region ----- copy + + /** + * 拷贝资源到目标文件 + * + * + * @param src 源文件 + * @param target 目标文件或目录,目标不存在会自动创建(目录、文件都创建) + * @param isOverride 是否覆盖目标文件 + * @return 目标目录或文件 + * @throws IORuntimeException IO异常 + */ + public static File copy(final Resource src, final File target, final boolean isOverride) throws IORuntimeException { + Assert.notNull(src, "Src file must be not null!"); + Assert.notNull(target, "target file must be not null!"); + return copy( + src, + target.toPath(), + isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}) + .toFile(); + } + /** * 复制文件或目录
* 如果目标文件为目录,则将源文件以相同文件名拷贝到目标目录 @@ -976,6 +1003,7 @@ public class FileUtil extends PathUtil { isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}) .toFile(); } + // endregion /** * 移动文件或目录到目标中,例如: @@ -1052,6 +1080,8 @@ public class FileUtil extends PathUtil { return rename(file.toPath(), newName, isOverride).toFile(); } + // region ----- getCanonicalPath and getAbsolutePath + /** * 获取规范的绝对路径 * @@ -1160,6 +1190,7 @@ public class FileUtil extends PathUtil { // 给定的路径已经是绝对路径了 return CharUtil.SLASH == path.charAt(0) || ReUtil.isMatch(PATTERN_PATH_ABSOLUTE, path); } + // endregion /** * 判断是否为目录,如果path为null,则返回false @@ -2438,27 +2469,27 @@ public class FileUtil extends PathUtil { * 将流的内容写入文件
* 此方法会自动关闭输入流 * - * @param dest 目标文件 - * @param in 输入流 + * @param target 目标文件 + * @param in 输入流 * @return dest * @throws IORuntimeException IO异常 */ - public static File writeFromStream(final InputStream in, final File dest) throws IORuntimeException { - return writeFromStream(in, dest, true); + public static File writeFromStream(final InputStream in, final File target) throws IORuntimeException { + return writeFromStream(in, target, true); } /** * 将流的内容写入文件 * - * @param dest 目标文件 + * @param target 目标文件 * @param in 输入流 * @param isCloseIn 是否关闭输入流 * @return dest * @throws IORuntimeException IO异常 * @since 5.5.6 */ - public static File writeFromStream(final InputStream in, final File dest, final boolean isCloseIn) throws IORuntimeException { - return FileWriter.of(dest).writeFromStream(in, isCloseIn); + public static File writeFromStream(final InputStream in, final File target, final boolean isCloseIn) throws IORuntimeException { + return FileWriter.of(target).writeFromStream(in, isCloseIn); } /** @@ -2506,6 +2537,7 @@ public class FileUtil extends PathUtil { * @return 大小 */ public static String readableFileSize(final File file) { + Assert.notNull(file); return readableFileSize(file.length()); } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/PathUtil.java index 086156dd8..f320fbe17 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/PathUtil.java @@ -15,6 +15,9 @@ package org.dromara.hutool.core.io.file; import org.dromara.hutool.core.array.ArrayUtil; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; +import org.dromara.hutool.core.io.resource.FileResource; +import org.dromara.hutool.core.io.resource.Resource; +import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.util.CharsetUtil; import java.io.*; @@ -85,6 +88,7 @@ public class PathUtil { } } + // region ----- loop and walk /** * 递归遍历目录以及子目录中的所有文件
* 如果提供path为文件,直接返回过滤结果 @@ -151,8 +155,6 @@ public class PathUtil { return fileList; } - // region ----- walkFiles - /** * 遍历指定path下的文件并做处理 * @@ -224,6 +226,74 @@ public class PathUtil { PathDeleter.of(path).clean(); } + // region ----- copy + /** + * 拷贝资源到目标文件 + * + * + * @param src 源文件资源{@link Resource}实现 + * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @param options {@link StandardCopyOption} + * @return 目标Path + * @throws IORuntimeException IO异常 + * @since 5.8.27 + */ + public static Path copy(final Resource src, final Path target, final CopyOption... options) throws IORuntimeException { + Assert.notNull(src, "Source is null !"); + if (src instanceof FileResource) { + return copy(((FileResource) src).getFile().toPath(), target, options); + } + try (final InputStream stream = src.getStream()) { + return copy(stream, target, options); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 通过JDK7+的 {@link Files#copy(InputStream, Path, CopyOption...)} 方法拷贝文件 + * + * @param src 源文件流,使用后不闭流 + * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @param options {@link StandardCopyOption} + * @return 目标Path + * @throws IORuntimeException IO异常 + * @since 5.8.27 + */ + public static Path copy(final InputStream src, final Path target, final CopyOption... options) throws IORuntimeException { + Assert.notNull(target, "Destination File or directory is null !"); + + try { + Files.copy(src, target, options); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + + return target; + } + + /** + * 通过JDK7+的 {@link Files#copy(InputStream, Path, CopyOption...)} 方法拷贝文件 + * + * @param src 源文件流,使用后不闭流 + * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @return 拷贝bytes数 + * @throws IORuntimeException IO异常 + * @since 6.0.0 + */ + public static long copy(final Path src, final OutputStream target) throws IORuntimeException { + Assert.notNull(src, "Source is null !"); + + try { + return Files.copy(src, target); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + } + /** * 复制src到target中 *