描述:
我在 Java 8 中创建了一个 ZIP 文件,并尝试将一个目录及其所有子文件和目录复制到该 zip 文件中。
Path directory = Paths.get("P:\Java\Test\backups\test.zip");
// path to the world;
Path world = Paths.get("P:\Java\Test\world");
[...]
// Create a map which tells the file system to create a new file if it doesn't exist
ImmutableMap immutableMap = ImmutableMap.of("create", String.valueOf(Files.notExists(this.directory)));
// Get a file system provider which is capable of creating a ZIP file
FileSystemProvider zipProvider = FileSystemProvider.installedProviders().stream()
.filter(provider -> provider.getScheme().equals("jar")).findFirst().get();
// Create the file system
try (FileSystem fs = zipProvider.newFileSystem(this.directory, immutableMap)) {
try {
Files.walk(this.world).forEach((Path sourcePath) -> {
try {
CopyOption[] option = new CopyOption[] {
StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES
};
Path destination = this.directory.resolve(this.world.relativize(sourcePath));
Files.copy(sourcePath, destination,option);
} catch (IOException e) {
e.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
问题:
每当我添加行 Files.copy
将我的目录以及所有子目录和子文件复制到 zip 文件中时,我都会收到以下异常:java.nio。 file.AccessDeniedException:.\backups\test.zip
控制台输出:
在下面的堆栈跟踪中,我将类调用的行号更改为上面发布的代码片段的行号,以提高可读性,除了对 ThreadBackup.run 方法的调用之外。它基本上是代码与其他一些但不相关的事物一起执行的方法。
java.nio.file.AccessDeniedException: .\backups\tests.zip
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileCopy.copy(WindowsFileCopy.java:231)
at sun.nio.fs.WindowsFileSystemProvider.copy(WindowsFileSystemProvider.java:278)
at java.nio.file.Files.copy(Files.java:1274)
at serverutilities.backups.ThreadBackups.lambda$createZipFile$1(ThreadBackups.java:24)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at serverutilities.backups.ThreadBackups.createZipFile(ThreadBackups.java:18)
at serverutilities.backups.ThreadBackups.run(ThreadBackups.java:56)
at java.lang.Thread.run(Thread.java:748)
java.nio.file.NoSuchFileException: P:\Java\Test\backups\test.zip
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:90)
at sun.nio.fs.WindowsLinkSupport.getRealPath(WindowsLinkSupport.java:259)
at sun.nio.fs.WindowsPath.toRealPath(WindowsPath.java:836)
at sun.nio.fs.WindowsPath.toRealPath(WindowsPath.java:44)
at com.sun.nio.zipfs.ZipFileSystemProvider.removeFileSystem(ZipFileSystemProvider.java:322)
at com.sun.nio.zipfs.ZipFileSystem.close(ZipFileSystem.java:305)
at serverutilities.backups.ThreadBackups.createZipFile(ThreadBackups.java:32)
at serverutilities.backups.ThreadBackups.run(ThreadBackups.java:56)
at java.lang.Thread.run(Thread.java:748)
我注意到,每当我调用 Files.copy
方法时,ZIP 文件甚至都没有创建或至少没有保存,因此 NoSuchFileException
在 之后抛出>AccessDeniedException
对于我尝试复制的每个目录和文件都会抛出。
最佳答案
我从未使用过 java.nio.file,但是一旦我必须处理此类任务,我就使用了 java.util.zip,它非常简单,仅用于从目录创建 zip 文件
尽管如此,如果您无法更改用于归档目录的内容,那么此解决方案不会有太大帮助,但示例代码带有一些解释:
- 使用新的 ZipOutputStream 创建新的 ZIP 存档
- 遍历将使用 Files.walk 压缩的文件树
- 对于文件树的每个路径,打包条目。 ZipEntry 保存有关存档中单个文件的元数据
要使用它,只需使用 src 和目标.zip 的路径调用 packDir 方法
private static void packDir(Path src, Path dest) throws IOException {
try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(dest));
ZipOutputStream zo = new ZipOutputStream(out);
Stream<Path> dirStream = Files.walk(src)) {
dirStream.filter(p -> !p.equals(src)).forEach(path -> {
try {
packEntry(src, zo, path);
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
private static void packEntry(Path src, ZipOutputStream zo, Path path) throws IOException {
String name = src.relativize(path).toString().replace('\\', '/');
boolean isDir = Files.isDirectory(path);
if (isDir) {
name += "/";
}
ZipEntry e = new ZipEntry(name);
zo.putNextEntry(e);
if (!isDir) {
Files.copy(path, zo);
}
zo.closeEntry();
}
关于Java 将文件复制到 zip AccessDeniedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48468080/