Java 将文件复制到 zip AccessDeniedException

标签 java multithreading file java-8 zip

描述:

我在 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/

相关文章:

python - threading.Condition.wait() 未捕获 SIGTERM

Java InputStream读取问题

python - 在 Python 中创建一个临时 FIFO(命名管道)?

java - 在 SWT 浏览器小部件中获取选定的文本

java - 我应该使用 Java 8 默认方法来手动实现 Spring Data 存储库方法吗?

java - 如果未选择,则在 UI 中显示带有默认值的枚举值

java - 无法在 JavaMail 中设置文本和添加附件

java - 处理程序和调度程序之间的区别

c# - 在 C# 中使用线程构建分布式 DFS

asp.net - File.Exists从网络共享返回false