【问题标题】:Write to subdir in Zip? Using java.util.zip. ZipEntry.putNextEntry()写入 Zip 中的子目录?使用 java.util.zip。 ZipEntry.putNextEntry()
【发布时间】:2016-07-30 20:04:39
【问题描述】:

所以我创建了一个 zip,并通过创建一个以“\”结尾的 zip 条目在 zip 文件中创建了一个新的子文件夹。我将如何写入子文件夹?

我的问题是我在 for 循环中对我的 ZipOutputStream 进行了 putnextEntry 调用,因此在创建文件夹后,我然后跳转到写入不同 zip 文件的 for 循环。但它们与 zip 中的子目录写在同一级别。

我认为正在发生的事情是因为我将 putNextEntry 与第一个实际 zi​​p(不是 dir)条目一起使用,它正在关闭子文件夹并写入 zip 的根目录。有什么想法吗?

代码如下

private int endprocess() {
        try {
            zipFolder(ripPath, zipOutputPath, "rips");
            //zipFolder(destPDFfiles, zipOutputPath, "pdfs");
            this.returnCode = 0;
            //log.debug ( "Accumulator count: " + acount);
            log.debug("Equivest count: " + ecount);
            //log.debug ( "Assoc count: " + scount);
            processEndOfEnvelope();
        } catch (Exception reportException) {
            log.logError("Caught exception in creating.");
            reportException.printStackTrace();
            this.returnCode = 15;
        }

        return (this.returnCode);

    }
    public static void zipFolder(String srcFolder, String dest, String outputFolder){
        try{
            ZipOutputStream zos = null;
            FileOutputStream fos = null;
            fos = new FileOutputStream(dest + "\\newzip.zip");
            zos = new ZipOutputStream(fos);
            addFolderToZip(srcFolder, zos, outputFolder);
            zos.flush();
            zos.close();
        }catch(IOException e){
            log.logError("**********************");
            log.logError("IO Exception occurred");
            log.logError(e.getMessage());
            e.printStackTrace();
        }
    }
    private static void addFileToZip(String srcFile, ZipOutputStream zos, String outputFolder){
        try {
            File folder = new File(srcFile);
            if (folder.isDirectory()) {
                addFolderToZip(srcFile, zos, outputFolder);
            } else {
                byte[] buffer = new byte[1024];
                int length;
                FileInputStream fis = new FileInputStream(srcFile);
                ZipEntry ze = new ZipEntry("C:\\AWDAAV\\zip\\newzip.zip\\" + outputFolder + "\\" + folder.getName());
                zos.putNextEntry(ze);
                while ((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }
            }
        }catch(Exception e){
            log.logError("**********************");
            log.logError("Exception occurred");
            log.logError(e.getMessage());
            e.printStackTrace();
        }
    }

    private static void addFolderToZip(String srcFolder, ZipOutputStream zos, String outputFolder){
        try{
            File folder = new File(srcFolder);
            zos.putNextEntry(new ZipEntry(outputFolder + "\\"));
            for(String fileName : folder.list()){
                addFileToZip(srcFolder + "\\" + fileName, zos, outputFolder);
            }
        }catch(Exception e){
            log.logError("**********************");
            log.logError("Exception occurred");
            log.logError(e.getMessage());
            e.printStackTrace();
        }
    }

【问题讨论】:

    标签: java zip subdirectory


    【解决方案1】:

    我查看了您的代码,我认为 ZIP API 的工作方式与您的想法一样。

    只有你的路径名有一些逻辑错误。 您需要将路径名从本地名称转换为 zip 文件中的相对位置。 也许你在那个领域的某个地方感到困惑。

    这是我的建议:

    文件:org/example/Main.java

    package org.example;
    
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
        public static void main(String[] args) throws IOException {
            MyZip myZip = new MyZip();
            Path sourcePath = Paths.get("C:/Users/David/Desktop/a");
            Path targetPath = Paths.get("C:/Users/David/Desktop/zip/out.zip");
            Path zipPath = Paths.get("tadaa");
            myZip.zipFolder(sourcePath, targetPath.toFile(), zipPath);
        }
    
    }
    

    更新:main方法中的变量说明

    • sourcePath 是您希望将其内容包含在 zip 存档中的目录。
    • targetPath 是 zip 文件的输出路径。例如,将在该位置创建新的 zip 文件。
    • zipPath 是 zip 目录中的子目录,sourcePath 中的内容将被放置在其中。这个变量也可以设置为null。如果是nullsourcePath 将被放入新 zip 存档的根目录中。

    文件:org/example/MyZip.java

    package org.example;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.file.DirectoryStream;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;
    
    public class MyZip {
    
        public void zipFolder(Path base, File dest, Path zipFolder) throws IOException {
            try (FileOutputStream fos = new FileOutputStream(dest);
                    ZipOutputStream zos = new ZipOutputStream(fos)) {
                addFolderToZip(base.getParent(), base, zos, zipFolder);
            }
        }
    
        private void addFolderToZip(Path base, Path currentFolder, ZipOutputStream zos, Path zipFolder) throws IOException {
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(currentFolder)) {
                for(Path path : stream) {
                    Path relativePath = base != null ? base.relativize(path) : path;
                    Path pathInZip = zipFolder != null ? zipFolder.resolve(relativePath) : relativePath;
                    if(path.toFile().isDirectory()) {
                        zos.putNextEntry(new ZipEntry(pathInZip.toString() + "/"));
                        // recurse to sub directories
                        addFolderToZip(base, path, zos, zipFolder);
                    } else {
                        addFileToZip(path, pathInZip, zos);
                    }
                }
            }
        }
    
        private void addFileToZip(Path sourcePath, Path pathInZip, ZipOutputStream zos) throws IOException {
            byte[] buffer = new byte[1024];
            int length;
            try (FileInputStream fis = new FileInputStream(sourcePath.toFile())) {
                ZipEntry ze = new ZipEntry(pathInZip.toString());
                zos.putNextEntry(ze);
                while ((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }
            }
        }
    
    }
    

    【讨论】:

    • 我对 zipPath 变量的含义有点困惑。 zip文件是什么时候真正创建的? targetPath 是否应该指向 zip 中的子目录?
    • 我在我的答案中添加了对 main 方法中所有变量的解释。您也可以将代码复制并粘贴到 java 项目中,然后运行它以查看它的作用。当然你必须更改我在 main 方法中硬编码的路径。
    • 好的,完美的解决方案。我感谢您的帮助。我用静态方法把它变成了一个静态类,这样我就不必实例化 MyZip,所以它更像一个帮助类。我遇到的唯一另一个问题是,当我不止一次运行它时,它会覆盖我的 zip。所以我只能在 Zip 中创建 1 个子目录。我相信这与我对 FileOutputStream 的初始化有关。我会看看,如果我弄清楚了,会告诉你的。
    【解决方案2】:

    ZipEntry.setLevel(filepath[in your case, \folder]);

    【讨论】:

    • ZipEntry 类上没有 setLevel 方法。如果它确实有效,这就是我正在寻找的东西。
    • ZipEntry里没有,但ZipOutputStream里有,我想如果你在流初始化的时候设置路径,应该可以把任何信息运行到那个级别
    • ZipOutputStream 类中的.level 方法是设置压缩级别。我已经在 FileOutputStream 中设置了路径,但问题是我只创建了一次 FileOutputStream 来创建 .zip 文件。从那里我写入 .zip 目录中的一个文件夹。
    • .level 不会为您解决这个问题吗?还是正在重置?
    • 否 .level 设置压缩级别。你传入一个 int。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多