Java将包含文件和结构的子目录移动到父目录
尝试将文件与结构一起从子目录移动到父目录。我无法使用Java将包含文件和结构的子目录移动到父目录,java,nio,Java,Nio,尝试将文件与结构一起从子目录移动到父目录。我无法使用Files.move()完成此操作。为了说明这个问题,请参见下面的目录结构 $ tree . └── b ├── c │ ├── cfile.gtxgt │ └── d │ ├── dfile.txt │ └── e └── x └── y └── z ├── 2.txt
Files.move()
完成此操作。为了说明这个问题,请参见下面的目录结构
$ tree
.
└── b
├── c
│ ├── cfile.gtxgt
│ └── d
│ ├── dfile.txt
│ └── e
└── x
└── y
└── z
├── 2.txt
└── p
├── file1.txt
└── q
├── file
├── file2.txt
└── r
└── 123.txt
我想通过Java模拟下面的move命令
$ mv b/x/y/z/* b/c
b/x/y/z/2.txt -> b/c/2.txt
b/x/y/z/p -> b/c/p
输出应该类似于
$ tree
.
└── b
├── c
│ ├── 2.txt
│ ├── cfile.gtxgt
│ ├── d
│ │ ├── dfile.txt
│ │ └── e
│ └── p
│ ├── file1.txt
│ └── q
│ ├── file
│ ├── file2.txt
│ └── r
│ └── 123.txt
└── x
└── y
└── z
在此移动中,目录z
下的所有文件和目录都已移动到c
我尝试过这样做:
public static void main(String[] args) throws IOException{
String aPath = "/tmp/test/a/";
String relativePathTomove = "b/x/y/z/";
String relativePathToMoveTo = "b/c";
Files.move(Paths.get(aPath, relativePathTomove), Paths.get(aPath, relativePathToMoveTo), StandardCopyOption.REPLACE_EXISTING);
}
但是,这会导致抛出的java.nio.file.DirectoryNotEmptyException:/tmp/test/a/b/c
出现此异常,如果去掉REPLACE\u EXISTING
选项,则代码抛出java.nio.file.filealreadyExistException:/tmp/test/a/b/c
这个问题的答案是使用递归函数来解决这个问题。但在我的情况下,它将涉及进一步的复杂性,因为我甚至需要在新位置重新创建sub-dir结构
我没有尝试使用commons io
实用程序方法,因为这段代码似乎是先复制文件,然后从原始位置删除它们。在我的例子中,文件很大,因此这不是首选选项
如何在java中实现移动功能,而不必借助复制。个人文件移动是我唯一的选择吗
TLDR:如何在java中模拟mv
功能,将带有文件和结构的子目录移动到父目录 我最后做了这样一件事:
创建一个FileVisitor
实现,如下所示:
package com.test.files;
import org.apache.log4j.Logger;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Objects;
import static java.nio.file.FileVisitResult.TERMINATE;
public class MoveFileVisitor implements FileVisitor<Path> {
private static final Logger LOGGER = Logger.getLogger(MoveFileVisitor.class);
private final Path target;
private final Path source;
public MoveFileVisitor(@NotNull Path source, @NotNull Path target) {
this.target = Objects.requireNonNull(target);
this.source = Objects.requireNonNull(source);
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
Path relativePath = source.relativize(dir);
Path finalPath = target.resolve(relativePath);
Files.createDirectories(finalPath);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path relativePath = source.relativize(file);
Path finalLocation = target.resolve(relativePath);
Files.move(file, finalLocation);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
LOGGER.error("Failed to visit file during move" + file.toAbsolutePath(), exc);
return TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
}
我最终做了这样的事:
创建一个FileVisitor
实现,如下所示:
package com.test.files;
import org.apache.log4j.Logger;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Objects;
import static java.nio.file.FileVisitResult.TERMINATE;
public class MoveFileVisitor implements FileVisitor<Path> {
private static final Logger LOGGER = Logger.getLogger(MoveFileVisitor.class);
private final Path target;
private final Path source;
public MoveFileVisitor(@NotNull Path source, @NotNull Path target) {
this.target = Objects.requireNonNull(target);
this.source = Objects.requireNonNull(source);
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
Path relativePath = source.relativize(dir);
Path finalPath = target.resolve(relativePath);
Files.createDirectories(finalPath);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path relativePath = source.relativize(file);
Path finalLocation = target.resolve(relativePath);
Files.move(file, finalLocation);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
LOGGER.error("Failed to visit file during move" + file.toAbsolutePath(), exc);
return TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
}
你不需要这些。只要一个
File.rename()
和正确的参数,就可以在一行代码中完成全部工作。@user207421-我想你指的是方法。此方法的文档建议使用Files.move()
,它会引发上面列出的异常。另外,我不认为renameTo
会考虑到目标目录中有一些文件,这里的文件需要合并到这些文件中。如果所有这些都是可能的,你能给我正确的参数。我不想为已经实现的东西编写代码,你不需要这些。只要一个File.rename()
和正确的参数,就可以在一行代码中完成全部工作。@user207421-我想你指的是方法。此方法的文档建议使用Files.move()
,它会引发上面列出的异常。另外,我不认为renameTo
会考虑到目标目录中有一些文件,这里的文件需要合并到这些文件中。如果所有这些都是可能的,你能给我正确的参数。我讨厌为已经实现的东西编写代码。