在java中解压缩并使用密码重新压缩

时间:2015-06-25 08:44:46

标签: java zip4j

我正在尝试从文件夹中提取zip文件列表,然后使用密码重新压缩它们。问题是在重新压缩时,迭代/循环没有停止。此外,重新压缩文件应该是一个单独的zip文件,而不是将所有内容合并到一个zip。

以下是我的尝试:

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;

public class AddFilesWithAESEncryption2 {

    public AddFilesWithAESEncryption2() {

        try {
            //Extract Zip files as folders
            try {
                String ZipSourcePath = "E:/EZipTest/";
                String ExtractTo = "D:/DZipTest/";
                String files1;
                File folder1 = new File(ZipSourcePath);
                File[] listOfFiles1 = folder1.listFiles();

                for (int i = 0; i < listOfFiles1.length; i++) {
                    if (listOfFiles1[i].isFile()) {
                        files1 = listOfFiles1[i].getName();
                        String ZipFiles = "E:/EZipTest/" + files1;

                        try {
                            ZipFile zipFile = new ZipFile(ZipFiles);
                            List fileHeaderList = zipFile.getFileHeaders();
                            zipFile.extractAll(ExtractTo);
                        } catch (ZipException e) {
                            e.printStackTrace();
                        }
                    }
                }
                //Get list of folders    
                String DirectoryNames;
                String ExtractedDirectories1 = "D:/DZipTest/";
                File folder2 = new File(ExtractedDirectories1);
                File[] listOfFiles2 = folder2.listFiles();

                for (int i = 0; i < listOfFiles2.length; i++) {
                    if (listOfFiles2[i].isDirectory()) {
                        DirectoryNames = listOfFiles2[i].getName();
                        String ListOfDirectories = "D:/DZipTest/" + DirectoryNames;

                        //Get list of files
                        String ExtractedDirectories = ListOfDirectories;
                        File folder3 = new File(ExtractedDirectories);
                        File[] listOfFiles3 = folder3.listFiles();

                        for (int j = 0; j < listOfFiles3.length; j++) {
                            File file = listOfFiles3[j];
                            if (file.isFile()) {
                                String FileNames = file.getName();
                                System.out.println(ListOfDirectories + FileNames);

                                //Compress and zip the files
                                ZipFile zipFile = new ZipFile("D:/" + listOfFiles2[i].getName() + ".zip");
                                ArrayList filesToAdd = new ArrayList();
                                filesToAdd.add(new File(ListOfDirectories + FileNames));
                                ZipParameters parameters = new ZipParameters();
                                parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to deflate compression
                                parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
                                parameters.setEncryptFiles(true);
                                parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
                                parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
                                parameters.setPassword("test");
                                zipFile.addFiles(filesToAdd, parameters);
                            }
                        }
                    }
                }
            } catch (ZipException e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new AddFilesWithAESEncryption2();
    }
}

1 个答案:

答案 0 :(得分:2)

重构

重构代码将帮助您了解它的作用。它将揭示问题并立即确定修复。这是怎么回事。请注意,这不是一个完整的教程,但我希望你明白这一点。

首先,提取一个执行解压缩的好方法。标记第一个for循环内的所有内容,然后右键单击并选择Refactor / Extract Method...。将其命名为unzipFile。请注意,您现在拥有一个很小的,可能可重用且可能可测试的(JUnit)方法。

接下来,标记从ZipParameters parametersparameters.setPassword("test");的所有内容,右击,Refactor / Extract Method...。将其命名为getEncryptionParameters。请注意,如何从long方法中删除7行代码,并提高可读性。

右键点击parameters,然后选择Refactor / Inline ...。注意临时变量是如何消失的。

查看错误

如果您密切关注,那么就有一段代码:

//Compress and zip the files
ZipFile zipFile = new ZipFile("D:/" + listOfFiles2[i].getName() + ".zip");
ArrayList filesToAdd = new ArrayList();
filesToAdd.add(new File(ListOfDirectories + FileNames));
zipFile.addFiles(filesToAdd, getEncryptionParameters());

看看它的作用?它会创建一个新的ZIP文件,只将一个文件添加到filesToAdd,就是这样。但为什么?它说FileNames。怎么只能是一个文件?

看着

String FileNames = file.getName();

这实际上只是一个文件,因此变量名称是错误的。

右键点击FileNames,然后选择Refactor/Rename...。输入fileName。请注意程序中的变量名称与实际名称的匹配程度。它大大提高了代码的可读性。

简化

现在您知道自己只添加了一个文件,请使用addFile()代替addFiles()。你摆脱了ArrayList

//Compress and zip the files
ZipFile zipFile = new ZipFile("D:/" + listOfFiles2[i].getName() + ".zip");
File fileToAdd = new File(ListOfDirectories + fileName);
zipFile.addFile(fileToAdd, getEncryptionParameters());

修复错误

如前所述,在循环内部创建了new ZipFile(...),并且只添加了一个文件。按 Alt + Up

将该行移出循环

继续重构

问题的一部分已经修复(实际上我没有尝试过),但是你的代码仍然没有错误。让我们继续:

标记从File[] listOfFiles3到后续for循环结尾的所有内容。右键单击Refactor/Extract Method...,将其命名为rezip。你的大方法再次变小。

右键点击ExtractedDirectoriesRefactor / Inline ...。你刚刚摆脱了一个不必要的临时变量。

看到什么?您的代码应如下所示:

//Get list of files
File folder3 = new File(ListOfDirectories);
rezip(listOfFiles2, i, ListOfDirectories, folder3);

请注意folder3ListOfDirectories基本相同。让我们摆脱它。将行File folder3 = new File(ListOfDirectories);移到方法中,在private void rezip(...){后面,并从File folder3的方法调用和方法声明中删除参数rezip()

使用rezip()的循环现在看起来像这样:

for (int i = 0; i < listOfFiles2.length; i++) {
    if (listOfFiles2[i].isDirectory()) {
        DirectoryNames = listOfFiles2[i].getName();
        String ListOfDirectories = "D:/DZipTest/" + DirectoryNames;
        rezip(listOfFiles2, i, ListOfDirectories);
    }
}

您可能会发现DirectoryNames实际上只是一个,而不是很多。右键单击Refactor/Rename...。输入subDirectory

右键点击subDirectoryRefactor / Inline ...。阅读错误消息。右键单击References / Workspace。检查结果并发现此变量仅在for循环中使用。删除外面的声明并在第一次使用时声明它。现在进行Refactor / Inline ...操作。

您的代码如下所示:

for (int i = 0; i < listOfFiles2.length; i++) {
    if (listOfFiles2[i].isDirectory()) {
        String ListOfDirectories = "D:/DZipTest/" + listOfFiles2[i].getName();
        rezip(listOfFiles2, i, ListOfDirectories);
    }
}

同样,有一个变量名称表示列表或数组,但事实并非如此。 Refactor / Rename...,将其命名为directoryToZip

按以下顺序内联以下变量:ExtractedDirectories1folder2ZipSourcePathfolder1

按此顺序重命名listOfFiles1zipFileslistOfFiles2extractedDirectories

删除files1,因为它从未使用过。

最后的错误

该方法现在简短易读,可以完全理解。以下是否有意义?

String ExtractTo = "D:/DZipTest/";
File[] zipFiles = new File("E:/EZipTest/").listFiles();
for (int i = 0; i < zipFiles.length; i++) {
    unzipFile(ExtractTo, zipFiles, i);
}

File[] extractedDirectories = new File("D:/DZipTest/").listFiles();
for (int i = 0; i < extractedDirectories.length; i++) {
    if (extractedDirectories[i].isDirectory()) {
        String directoryToZip = "D:/DZipTest/" + extractedDirectories[i].getName();
        rezip(extractedDirectories, i, directoryToZip);
    }
}

不,不。

  1. 您不想先提取所有档案,而是逐一提取
  2. 您不想压缩子目录,您想要压缩ExtractTo目录中的所有内容
  3. 修复最终错误

    unzipFile()的签名看起来不正确。如果它只是顾名思义解压缩一个文件,为什么它可以访问所有文件呢?

    unzipFile(ExtractTo, zipFiles, i);替换为unzipFile(ExtractTo, zipFiles[i]);。这打破了代码。 Eclipse会将其标记为红色。通过更改

    中的参数来修复它
    private void unzipFile(String ExtractTo, File[] listOfFiles1, int i)
    

    private void unzipFile(String ExtractTo, File listOfFiles1)
    

    unzip内,将listOfFiles1[i]替换为listOfFiles1。然后Refactor/Rename...将其sourceZipFile

    类似于rezip方法:它应该获取zip目录和目标文件名。因此改变

    rezip(extractedDirectories, i, directoryToZip);
    

    rezip(extractedDirectories[i], directoryToZip);
    

    然后从

    调整方法本身
    private void rezip(File[] listOfFiles2, int i, String ListOfDirectories) throws ZipException
    

    private void rezip(File listOfFiles2, String ListOfDirectories) throws ZipException
    

    然后将listOfFiles2[i]更改为listOfFiles2。将其重命名为targetFile

    现在你有一个很好的unzipFile()方法和一个rezip()方法。让我们以一种很酷的方式结合它:

    String ExtractTo = "D:/DZipTest/";
    File[] zipFiles = new File("E:/EZipTest/").listFiles();
    for (int i = 0; i < zipFiles.length; i++) {
        unzipFile(ExtractTo, zipFiles[i]);
        rezip(zipFiles[i], ExtractTo);
        // TODO: delete extracted files here
    }
    

    太棒了,不是吗?

    备注

    也许您已经看到了解代码并提供修复所付出的努力。实际上,Stack Overflow的工作量太大了。下次您提出问题时,请尝试提供与您的代码一样可读的最小代码。

    代码仍然没有应有的清晰。花更多的时间在上面。如果你认为它很棒,可以在https://codereview.stackexchange.com/上发布,以获得更多指示。