fix move bug

This commit is contained in:
Looly 2020-11-15 11:15:03 +08:00
parent 8102c89903
commit ea3060cddf
7 changed files with 58 additions and 41 deletions

View File

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

View File

@ -968,41 +968,13 @@ public class FileUtil extends PathUtil {
* 移动文件或者目录 * 移动文件或者目录
* *
* @param src 源文件或者目录 * @param src 源文件或者目录
* @param dest 目标文件或者目录 * @param target 目标文件或者目录
* @param isOverride 是否覆盖目标只有目标为文件才覆盖 * @param isOverride 是否覆盖目标只有目标为文件才覆盖
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
* @see PathUtil#move(Path, Path, boolean)
*/ */
public static void move(File src, File dest, boolean isOverride) throws IORuntimeException { public static void move(File src, File target, boolean isOverride) throws IORuntimeException {
// check move(src.toPath(), target.toPath(), isOverride);
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);
}
} }
/** /**

View File

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

View File

@ -66,7 +66,7 @@ public class PathUtil {
if (null == path || false == Files.exists(path)) { if (null == path || false == Files.exists(path)) {
return fileList; return fileList;
} else if (false == Files.isDirectory(path)) { } else if (false == isDirectory(path)) {
final File file = path.toFile(); final File file = path.toFile();
if (null == fileFilter || fileFilter.accept(file)) { if (null == fileFilter || fileFilter.accept(file)) {
fileList.add(file); fileList.add(file);
@ -112,7 +112,7 @@ public class PathUtil {
} }
/** /**
* 删除文件或者文件夹<br> * 删除文件或者文件夹不追踪软链<br>
* 注意删除文件夹时不会判断文件夹是否为空如果不空则递归删除子文件或文件夹<br> * 注意删除文件夹时不会判断文件夹是否为空如果不空则递归删除子文件或文件夹<br>
* 某个文件删除失败会终止删除操作 * 某个文件删除失败会终止删除操作
* *
@ -127,7 +127,7 @@ public class PathUtil {
} }
try { try {
if (Files.isDirectory(path)) { if (isDirectory(path)) {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() { Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override @Override
@ -182,7 +182,7 @@ public class PathUtil {
Assert.notNull(src, "Source File is null !"); Assert.notNull(src, "Source File is null !");
Assert.notNull(dest, "Destination File or directiory 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 { try {
return Files.copy(src, destPath, options); return Files.copy(src, destPath, options);
} catch (IOException e) { } catch (IOException e) {
@ -190,6 +190,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 * 判断是否为目录如果file为null则返回false
* *
@ -370,9 +382,28 @@ public class PathUtil {
* @since 5.4.1 * @since 5.4.1
*/ */
public static Path rename(Path path, String newName, boolean isOverride) { 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[]{}; final CopyOption[] options = isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{};
if (isDirectory(target)) {
target = target.resolve(src.getFileName());
}
try { try {
return Files.move(path, path.resolveSibling(newName), options); return Files.move(src, target, options);
} catch (IOException e) { } catch (IOException e) {
throw new IORuntimeException(e); throw new IORuntimeException(e);
} }

View File

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

View File

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

View File

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