gpt4 book ai didi

java - 提取zip并使用Java中的密码重新压缩

转载 作者:行者123 更新时间:2023-12-02 12:24:26 24 4
gpt4 key购买 nike

我试图从文件夹中提取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();
}
}

最佳答案

重构

重构代码将帮助您了解其功能。它将发现问题并立即确定解决方案。这是怎么回事。请注意,这不是完整的教程,但是希望您能理解。

首先,提取一个不错的方法来解压缩。标记第一个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 +向上键将该行移出循环。

继续重构

问题的一部分已经解决(实际上,我还没有尝试过),但是您的代码仍然不是没有错误的。我们继续:

标记所有内容,从 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

以此顺序将 listOfFiles1重命名为 zipFiles,并将 listOfFiles2重命名为 extractedDirectories

删除 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);
}
}

不,不是。
  • 您不想首先提取所有存档,而是一个接一个地提取
  • 您不想压缩子目录,而是想压缩ExtractTo目录中的所有内容

  • 修复最后的错误
    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方法类似:它应仅获取要压缩的目录和目标文件名。因此改变
    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
    }

    很棒,不是吗?

    笔记

    也许您已经了解了理解代码并提供修复的工作量。实际上,对于堆栈溢出,需要付出太多努力。下次您提出问题时,请尝试提供与现在的代码一样可读的代码。

    该代码仍未达到应有的清晰程度。花更多的时间在它上面。如果您认为它很棒,请将其发布在 https://codereview.stackexchange.com/上以获得更多说明。

    关于java - 提取zip并使用Java中的密码重新压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31045390/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com