Browse Source

fix move bug

Looly 5 years ago
parent
commit
ea3060cddf

+ 1 - 0
CHANGELOG.md

@@ -7,6 +7,7 @@
 
 ### 新特性
 ### Bug修复
+* 【core   】     修复在Linux下FileUtil.move失败问题(issue#I254Y3@Gitee)
 
 -------------------------------------------------------------------------------------------------------------
 

+ 4 - 32
hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java

@@ -968,41 +968,13 @@ public class FileUtil extends PathUtil {
 	 * 移动文件或者目录
 	 *
 	 * @param src        源文件或者目录
-	 * @param dest       目标文件或者目录
+	 * @param target       目标文件或者目录
 	 * @param isOverride 是否覆盖目标,只有目标为文件才覆盖
 	 * @throws IORuntimeException IO异常
+	 * @see PathUtil#move(Path, Path, boolean)
 	 */
-	public static void move(File src, File dest, boolean isOverride) throws IORuntimeException {
-		// check
-		if (false == src.exists()) {
-			throw new IORuntimeException("File not found: " + src);
-		}
-
-		// 来源为文件夹,目标为文件
-		if (src.isDirectory() && dest.isFile()) {
-			throw new IORuntimeException(StrUtil.format("Can not move directory [{}] to file [{}]", src, dest));
-		}
-
-		if (isOverride && dest.isFile()) {// 只有目标为文件的情况下覆盖之
-			//noinspection ResultOfMethodCallIgnored
-			dest.delete();
-		}
-
-		// 来源为文件,目标为文件夹
-		if (src.isFile() && dest.isDirectory()) {
-			dest = new File(dest, src.getName());
-		}
-
-		if (false == src.renameTo(dest)) {
-			// 在文件系统不同的情况下,renameTo会失败,此时使用copy,然后删除原文件
-			try {
-				copy(src, dest, isOverride);
-			} catch (Exception e) {
-				throw new IORuntimeException(StrUtil.format("Move [{}] to [{}] failed!", src, dest), e);
-			}
-			// 复制后删除源
-			del(src);
-		}
+	public static void move(File src, File target, boolean isOverride) throws IORuntimeException {
+		move(src.toPath(), target.toPath(), isOverride);
 	}
 
 	/**

+ 4 - 4
hutool-core/src/main/java/cn/hutool/core/io/file/FileCopier.java

@@ -44,7 +44,7 @@ public class FileCopier extends SrcToDestCopier<File, FileCopier>{
 	 * 新建一个文件复制器
 	 * @param srcPath 源文件路径(相对ClassPath路径或绝对路径)
 	 * @param destPath 目标文件路径(相对ClassPath路径或绝对路径)
-	 * @return {@link FileCopier}
+	 * @return this
 	 */
 	public static FileCopier create(String srcPath, String destPath) {
 		return new FileCopier(FileUtil.file(srcPath), FileUtil.file(destPath));
@@ -54,7 +54,7 @@ public class FileCopier extends SrcToDestCopier<File, FileCopier>{
 	 * 新建一个文件复制器
 	 * @param src 源文件
 	 * @param dest 目标文件
-	 * @return {@link FileCopier}
+	 * @return this
 	 */
 	public static FileCopier create(File src, File dest) {
 		return new FileCopier(src, dest);
@@ -188,8 +188,8 @@ public class FileCopier extends SrcToDestCopier<File, FileCopier>{
 				throw new IORuntimeException("Dest is a sub directory of src !");
 			}
 			
-			final File subDest = isCopyContentIfDir ? dest : FileUtil.mkdir(FileUtil.file(dest, src.getName()));
-			internalCopyDirContent(src, subDest);
+			final File subTarget = isCopyContentIfDir ? dest : FileUtil.mkdir(FileUtil.file(dest, src.getName()));
+			internalCopyDirContent(src, subTarget);
 		} else {// 复制文件
 			internalCopyFile(src, dest);
 		}

+ 36 - 5
hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java

@@ -66,7 +66,7 @@ public class PathUtil {
 
 		if (null == path || false == Files.exists(path)) {
 			return fileList;
-		} else if (false == Files.isDirectory(path)) {
+		} else if (false == isDirectory(path)) {
 			final File file = path.toFile();
 			if (null == fileFilter || fileFilter.accept(file)) {
 				fileList.add(file);
@@ -112,7 +112,7 @@ public class PathUtil {
 	}
 
 	/**
-	 * 删除文件或者文件夹<br>
+	 * 删除文件或者文件夹,不追踪软链<br>
 	 * 注意:删除文件夹时不会判断文件夹是否为空,如果不空则递归删除子文件或文件夹<br>
 	 * 某个文件删除失败会终止删除操作
 	 *
@@ -127,7 +127,7 @@ public class PathUtil {
 		}
 
 		try {
-			if (Files.isDirectory(path)) {
+			if (isDirectory(path)) {
 				Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
 
 					@Override
@@ -182,7 +182,7 @@ public class PathUtil {
 		Assert.notNull(src, "Source File is null !");
 		Assert.notNull(dest, "Destination File or directiory is null !");
 
-		Path destPath = dest.toFile().isDirectory() ? dest.resolve(src.getFileName()) : dest;
+		Path destPath = isDirectory(dest) ? dest.resolve(src.getFileName()) : dest;
 		try {
 			return Files.copy(src, destPath, options);
 		} catch (IOException e) {
@@ -191,6 +191,18 @@ public class PathUtil {
 	}
 
 	/**
+	 * 判断是否为目录,如果file为null,则返回false<br>
+	 * 此方法不会追踪到软链对应的真实地址,即软链被当作文件
+	 *
+	 * @param path          {@link Path}
+	 * @return 如果为目录true
+	 * @since 5.5.1
+	 */
+	public static boolean isDirectory(Path path) {
+		return isDirectory(path, false);
+	}
+
+	/**
 	 * 判断是否为目录,如果file为null,则返回false
 	 *
 	 * @param path          {@link Path}
@@ -370,9 +382,28 @@ public class PathUtil {
 	 * @since 5.4.1
 	 */
 	public static Path rename(Path path, String newName, boolean isOverride) {
+		return move(path, path.resolveSibling(newName), isOverride);
+	}
+
+	/**
+	 * 移动文件或目录<br>
+	 * 当目标是目录时,会将源文件或文件夹整体移动至目标目录下
+	 *
+	 * @param src        源文件或目录路径
+	 * @param target     目标路径,如果为目录,则移动到此目录下
+	 * @param isOverride 是否覆盖目标文件
+	 * @return 目标文件Path
+	 * @since 5.5.1
+	 */
+	public static Path move(Path src, Path target, boolean isOverride) {
+		Assert.notNull(src, "Src path must be not null !");
+		Assert.notNull(target, "Target path must be not null !");
 		final CopyOption[] options = isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{};
+		if (isDirectory(target)) {
+			target = target.resolve(src.getFileName());
+		}
 		try {
-			return Files.move(path, path.resolveSibling(newName), options);
+			return Files.move(src, target, options);
 		} catch (IOException e) {
 			throw new IORuntimeException(e);
 		}

+ 6 - 0
hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java

@@ -74,6 +74,12 @@ public class FileUtilTest {
 	}
 
 	@Test
+	@Ignore
+	public void renameTest2() {
+		FileUtil.move(FileUtil.file("d:/test/a"), FileUtil.file("d:/test/b"), false);
+	}
+
+	@Test
 	public void copyTest() {
 		File srcFile = FileUtil.file("hutool.jpg");
 		File destFile = FileUtil.file("hutool.copy.jpg");

+ 6 - 0
hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java

@@ -18,4 +18,10 @@ public class PathUtilTest {
 				StandardCopyOption.REPLACE_EXISTING
 				);
 	}
+
+	@Test
+	@Ignore
+	public void moveTest(){
+		PathUtil.move(Paths.get("d:/lombok.jar"), Paths.get("d:/test/"), false);
+	}
 }

+ 1 - 0
hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java

@@ -187,6 +187,7 @@ public class ExcelReadTest {
 	}
 
 	@Test
+	@Ignore
 	public void readCellsTest() {
 		final ExcelReader reader = ExcelUtil.getReader("merge_test.xlsx");
 		reader.read((cell, value)-> Console.log("{}, {} {}", cell.getRowIndex(), cell.getColumnIndex(), value));