Zip не разархивирует директорию с вложенными файлами

У меня есть код, который разархивирует zip файл, но не работает при разархивировании заархивированной директории -

public static String unZipFile(String fileZip) throws IOException {
    File destDir = new File(System.getProperty("user.dir"));
    byte[] buffer = new byte[1024];
    ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip));
    ZipEntry zipEntry = zis.getNextEntry();
    while (zipEntry != null) {
        File newFile = newFile(destDir, zipEntry);
        FileOutputStream fos = new FileOutputStream(newFile);
        int len;
        while ((len = zis.read(buffer)) > 0) {
            fos.write(buffer, 0, len);
        }
        fos.close();
        zipEntry = zis.getNextEntry();
    }
    zis.closeEntry();
    zis.close();
    return destDir.toString();
}

public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
    File destFile = new File(destinationDir, zipEntry.getName());

    String destDirPath = destinationDir.getCanonicalPath();
    String destFilePath = destFile.getCanonicalPath();

    if (!destFilePath.startsWith(destDirPath + File.separator)) {
        throw new IOException("Entry is outside of the target dir: " +
                zipEntry.getName());
    }
    return destFile;
}

Командная строка ругается -

   `C:\Users\phil\Desktop>java -jar c:\Users\phil\Desktop\Archiver-1.0- 
    SNAPSHOT.jar c:\Users\phil\Desktop\dirCompressed.zip
    Exception in thread "main" java.io.FileNotFoundException: 
    C:\Users\phil\Desktop\Text (Отказано в доступе)
        at java.base/java.io.FileOutputStream.open0(Native Method)
        at java.base/java.io.FileOutputStream.open(FileOutputStream.java:291)
        at java.base/java.io.FileOutputStream.<init> 
    (FileOutputStream.java:234)
        at java.base/java.io.FileOutputStream.<init> 
    (FileOutputStream.java:184)
        at ZipArchiver.unZipFile(ZipArchiver.java:79)
        at Main.main(Main.java:9)`

Что я неправильно делаю?


Ответы (1 шт):

Автор решения: Alexandr

Необходимо проверять является ли zipEntry директорией. И в этом случае нужно не записывать файл из архива, а создавать новую директорию.

Path destDir = Paths.get(System.getProperty("user.dir"));
try (FileInputStream fis = new FileInputStream(fileZip);
     ZipInputStream zis = new ZipInputStream(fis)) {
    for (ZipEntry zipEntry; (zipEntry = zis.getNextEntry()) != null; ) {
        Path resolvedPath = destDir.resolve(zipEntry.getName());
        if (zipEntry.isDirectory()) {
            Files.createDirectories(resolvedPath);
        } else {
            Files.copy(zis, resolvedPath);
        }
    }
}

Похожие обсуждения в английской версии:

→ Ссылка