我正在尝试从文件夹中提取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();
}
}
答案 0 :(得分:2)
重构代码将帮助您了解它的作用。它将揭示问题并立即确定修复。这是怎么回事。请注意,这不是一个完整的教程,但我希望你明白这一点。
首先,提取一个执行解压缩的好方法。标记第一个for
循环内的所有内容,然后右键单击并选择Refactor / Extract Method...
。将其命名为unzipFile
。请注意,您现在拥有一个很小的,可能可重用且可能可测试的(JUnit)方法。
接下来,标记从ZipParameters parameters
到parameters.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
。你的大方法再次变小。
右键点击ExtractedDirectories
,Refactor / Inline ...
。你刚刚摆脱了一个不必要的临时变量。
看到什么?您的代码应如下所示:
//Get list of files
File folder3 = new File(ListOfDirectories);
rezip(listOfFiles2, i, ListOfDirectories, folder3);
请注意folder3
和ListOfDirectories
基本相同。让我们摆脱它。将行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
。
右键点击subDirectory
,Refactor / 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
。
按以下顺序内联以下变量:ExtractedDirectories1
,folder2
,ZipSourcePath
,folder1
。
按此顺序重命名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
方法:它应该获取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/上发布,以获得更多指示。