Gitee: https://gitee.com/mirrors/zip4j
特征
:
帮助文档
: https://gitee.com/mirrors/zip4j/blob/master/README.md
<dependency>
<groupId>net.lingala.zip4jgroupId>
<artifactId>zip4jartifactId>
<version>2.6.1version>
dependency>
new ZipFile("filename.zip").addFile("filename.ext");
Or
new ZipFile("filename.zip").addFile(new File("filename.ext"));
new ZipFile("filename.zip").addFiles(Arrays.asList(new File("first_file"), new File("second_file")));
new ZipFile("filename.zip").addFolder(new File("/users/some_user/folder_to_add"));
从v2.6开始,可以使用ExcludeFileFilter在将文件夹添加到zip时排除某些文件
ExcludeFileFilter excludeFileFilter = filesToExclude::contains;
ZipParameters zipParameters = new ZipParameters();
zipParameters.setExcludeFileFilter(excludeFileFilter);
new ZipFile("filename.zip").addFolder(new File("/users/some_user/folder_to_add"), zipParameters);
new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());
传递new ZipParameters()
,如上面的例子中,将Zip4j使用默认参数拉链。请查看 ZipParameters以查看默认配置。
默认情况下,Zip4j使用Deflate压缩算法来压缩文件。但是,如果您不想使用任何压缩(称为存储压缩),可以按照以下示例所示进行操作:
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(CompressionMethod.STORE);
new ZipFile("filename.zip").addFile("fileToAdd", zipParameters);
您可以类似地将zip参数传递给所有其他示例,以创建一个STORE压缩的zip文件。
ZipParameters zipParameters = new ZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
//下面的行是可选的。默认情况下使用AES 256。您可以覆盖它以使用AES128。AES192仅支持提取。
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
List<File> filesToAdd = Arrays.asList(
new File("somefile"),
new File("someotherfile")
);
ZipFile zipFile = new ZipFile("filename.zip", "password".toCharArray());
zipFile.addFiles(filesToAdd, zipParameters);
代替AES,替换zipParameters.setEncryptionMethod(EncryptionMethod.AES)
;为 zipParameters.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
。您可以省略该行以设置Aes Key强度。顾名思义,这仅适用于AES加密。
在以上所有示例中,您可以类似地传入具有适当密码配置的zip参数以创建受密码保护的zip文件
如果要在大小超过特定限制时将zip文件拆分为多个文件,可以这样进行:
List<File> filesToAdd = Arrays.asList(
new File("somefile"),
new File("someotherfile")
);
ZipFile zipFile = new ZipFile("filename.zip");
zipFile.createSplitZipFile(filesToAdd, new ZipParameters(), true, 10485760); //在此示例中使用10MB
传递new ZipParameters()
,如上面的例子中,将Zip4j使用默认参数拉链。请查看 ZipParameters
以查看默认配置。
压缩文件格式指定最小65536字节(64kb)作为拆分文件的最小长度。如果指定的值小于此值,Zip4j将引发异常。
要创建具有密码保护的拆分zip,请传递适当的ZipParameters
,如下例所示:
ZipParameters zipParameters = new ZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
List<File> filesToAdd = Arrays.asList(
new File("somefile"),
new File("someotherfile")
);
ZipFile zipFile = new ZipFile("filename.zip", "password".toCharArray());
zipFile.createSplitZipFile(filesToAdd, zipParameters, true, 10485760); //在此示例中使用10MB
Zip64是一种zip功能,当zip文件的大小超过可以存储在4个字节中的最大值(即大于4,294,967,295字节)时,便支持zip文件。传统上,zip标头提供4个字节来存储文件大小。但是与几十年前相比,随着文件大小的增长,zip文件格式扩展了对文件大小的支持,通过添加额外的标头扩展了4个字节,这些标头使用8个字节作为文件大小(压缩和未压缩的文件大小)。此功能称为Zip64。
当Zip4j检测到zip文件超出此文件大小限制时,它将自动将其压缩为Zip64格式并添加适当的标头。您无需为Zip4j明确指定任何标志即可使用此功能
new ZipFile("filename.zip").extractAll("/destination_directory");
new ZipFile("filename.zip", "password".toCharArray()).extractAll("/destination_directory");
new ZipFile("filename.zip").extractFile("fileNameInZip.txt", "/destination_directory");
new ZipFile("filename.zip").extractFile("folderNameInZip/", "/destination_directory");
new ZipFile("filename.zip", "password".toCharArray()).extractFile("fileNameInZip.txt", "/destination_directory");
从v2.6.0开始:如果文件名表示目录,则zip4j将提取zip中属于该目录的所有文件。
下面的示例将从fileNameInZip.txtzip
文件中提取文件到输出目录/destination_directory
,并为文件命名newfileName.txt
。如果没有新文件名的第三个参数,将使用与zip中的文件相同的名称,本例中为fileNameInZip.txt。
如果要提取的文件是目录,newFileName
则将参数用作目录名。
new ZipFile("filename.zip", "password".toCharArray()).extractFile("fileNameInZip.txt", "/destination_directory", "newfileName.txt");
ZipFile zipFile = new ZipFile("filename.zip");
FileHeader fileHeader = zipFile.getFileHeader("entry_name_in_zip.txt");
InputStream inputStream = zipFile.getInputStream(fileHeader);
现在,您可以使用此输入流从其中读取内容/将内容写入输出流。请注意,条目/文件名是相对于其所在目录的。如果entry_name_in_zip.txt
位于zip的
“root_folder ”文件夹中,则可以使用zipFile.getFileHeader("root_folder/entry_name_in_zip.txt");
new ZipFile("filename.zip").removeFile("fileNameInZipToRemove");
如果fileNameInZipToRemove
代表一个文件夹。该文件夹下的所有文件和文件夹也将被删除(自zip4j v2.5.0起有效。所有先前版本仅删除单个条目,即使它是文件夹)。
请注意,文件名是zip中根目录的相对名称。也就是说,如果要删除的文件存在于名为“ folder1”的文件夹中,而该文件夹又存在于名为“ root-folder”的文件夹中,则可以按以下步骤从zip中删除该文件:
new ZipFile("filename.zip").removeFile("root-folder/folder1/fileNameInZipToRemove");
如果要确定要删除的文件存在于zip文件中,或者如果不想在处理removeFileapi 时将文件名作为字符串处理,则可以使用其他重载方法,该方法采用FileHeader:
ZipFile zipFile = new ZipFile("someZip.zip");
FileHeader fileHeader = zipFile.getFileHeader("fileNameInZipToRemove");
if (fileHeader == null) {
// file does not exist
}
zipFile.removeFile(fileHeader);
从zip4j v2.5.0开始,可以从zip文件中删除多个文件和文件夹。现在,您可以传递一个列表,如下面的代码所示:
ZipFile zipFile = new ZipFile("someZip.zip");
List<String> filesToRemove = Arrays.asList("file1.txt", "file2.txt", "some-folder/", "some-new-folder-1/somefile.pdf");
zipFile.removeFiles(filesToRemove);
上面的代码将删除file1.txt,file2.txt下的所有文件和文件夹some-folder(包括some-folder)和刚进入somefile.pdf的文件夹中some-new-folder-1。所有其他文件和文件夹在zip文件中均保持不变。
有三种方法可以使用zip4j重命名zip文件中的条目。一种方法是传递文件头和新文件名:
ZipFile zipFile = new ZipFile("sample.zip");
FileHeader fileHeader = zipFile.getFileHeader("entry-to-be-changed.pdf");
zipFile.renameFile(fileHeader, "new-file-name.pdf");
第二种方法是只传入要更改的文件名(而不是文件头)和新文件名。
new ZipFile("filename.zip").renameFile("entry-to-be-changed.pdf", "new-file-name.pdf");
也可以一次更改多个文件名。在这种情况下,您必须使用一个映射,该映射中条目的键是要更改的条目,而映射的值是新文件名:
Map<String, String> fileNamesMap = new HashMap<>();
fileNamesMap.put("firstFile.txt", "newFileFirst.txt");
fileNamesMap.put("secondFile.pdf", "newSecondFile.pdf");
fileNamesMap.put("some-folder/thirdFile.bin", "some-folder/newThirdFile.bin");
new ZipFile("filename.zip").renameFile("entry-to-be-changed.pdf", "new-file-name.pdf");
要修改文件夹内的条目名称,新文件名也应包含完整的父路径。例如,如果some-entry.pdf文件夹中包含按名称命名的条目,则some-folder/some-sub-folder/
将该条目名称修改为some-new-entry.pdf:
new ZipFile("filename.zip").renameFile("some-folder/some-sub-folder/some-entry.pdf", "some-folder/some-sub-folder/new-entry.pdf");
如果缺少父路径路径,则该文件将放在zip文件的根目录中。在下面的示例中,文件重命名后,some-new-entry.pdf将存在于zip文件的根目录中,而不是位于some-folder/some-sub-folder/:
new ZipFile("filename.zip").renameFile("some-folder/some-sub-folder/some-entry.pdf", "some-new-entry.pdf");
这也提供了将条目“移动”到另一个文件夹的灵活性。下面的例子将移动 some-entry.pdf从some-folder/some-sub-folder/到folder-to-be-moved-to/sub-folder/该文件也将被重新命名为new-entry.pdf。要仅移动文件,请使用相同的文件名而不是新文件名。
new ZipFile("filename.zip").renameFile("some-folder/some-sub-folder/some-entry.pdf", "folder-to-be-moved-to/sub-folder/new-entry.pdf");
如果要修改的条目是目录,则该目录中的所有条目都将被重命名,以便所有这些条目都具有新的文件夹名称作为父文件夹。以zip格式,目录下的所有条目名称都将包含全名作为其文件名。例如,如果有一个由名称的条目filename.txt的目录里面directoryName,条目的文件名会directoryName/filename.txt。并且,如果目录名现在已更改为newDirectoryName,则其下的条目也将更改为newDirectoryName/filename.txt,因此提取zip文件时,该目录 filename.txt将位于下newDirectoryName。
压缩文件格式不允许修改拆分的zip文件,如果尝试重命名拆分的zip文件中的文件,zip4j将引发异常。
这与创建拆分的zip文件相反,也就是说,此功能会将合并的zip文件(将多个文件拆分成一个zip文件)合并
new ZipFile("split_zip_file.zip").mergeSplitFiles(new File("merged_zip_file.zip"));
如果拆分的zip文件(在本例中split_zip_file.zip)不是拆分的zip文件,则此方法将引发异常
List<FileHeader> fileHeaders = new ZipFile("zipfile.zip").getFileHeaders();
fileHeaders.stream().forEach(fileHeader -> System.out.println(fileHeader.getFileName()));
您可以从FileHeader与zip中每个文件/条目相对应的对象中获取所有其他信息。
new ZipFile("encrypted_zip_file.zip").isEncrypted();
new ZipFile("split_zip_file.zip").isSplitArchive();
new ZipFile("some_zip_file.zip").setComment("Some comment");
new ZipFile("some_zip_file.zip").setComment("");
new ZipFile("some_zip_file.zip").getComment();
Note: This will only check for the validity of the headers and not the validity of each entry in the zip file.
new ZipFile("valid_zip_file.zip").isValidZipFile();
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class ZipOutputStreamExample {
public void zipOutputStreamExample(File outputZipFile, List<File> filesToAdd, char[] password,
CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength)
throws IOException {
ZipParameters zipParameters = buildZipParameters(compressionMethod, encrypt, encryptionMethod, aesKeyStrength);
byte[] buff = new byte[4096];
int readLen;
try(ZipOutputStream zos = initializeZipOutputStream(outputZipFile, encrypt, password)) {
for (File fileToAdd : filesToAdd) {
//条目大小有,如果你想添加STORE压缩方法(不压缩)的条目设置
//这是不需要deflate压缩
if (zipParameters.getCompressionMethod() == CompressionMethod.STORE) {
zipParameters.setEntrySize(fileToAdd.length());
}
zipParameters.setFileNameInZip(fileToAdd.getName());
zos.putNextEntry(zipParameters);
try(InputStream inputStream = new FileInputStream(fileToAdd)) {
while ((readLen = inputStream.read(buff)) != -1) {
zos.write(buff, 0, readLen);
}
}
zos.closeEntry();
}
}
}
private ZipOutputStream initializeZipOutputStream(File outputZipFile, boolean encrypt, char[] password)
throws IOException {
FileOutputStream fos = new FileOutputStream(outputZipFile);
if (encrypt) {
return new ZipOutputStream(fos, password);
}
return new ZipOutputStream(fos);
}
private ZipParameters buildZipParameters(CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength) {
ZipParameters zipParameters = new ZipParameters();
zipParameters.setCompressionMethod(compressionMethod);
zipParameters.setEncryptionMethod(encryptionMethod);
zipParameters.setAesKeyStrength(aesKeyStrength);
zipParameters.setEncryptFiles(encrypt);
return zipParameters;
}
}
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.LocalFileHeader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class ZipInputStreamExample {
public void extractWithZipInputStream(File zipFile, char[] password) throws IOException {
LocalFileHeader localFileHeader;
int readLen;
byte[] readBuffer = new byte[4096];
InputStream inputStream = new FileInputStream(zipFile);
try (ZipInputStream zipInputStream = new ZipInputStream(inputStream, password)) {
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
File extractedFile = new File(localFileHeader.getFileName());
try (OutputStream outputStream = new FileOutputStream(extractedFile)) {
while ((readLen = zipInputStream.read(readBuffer)) != -1) {
outputStream.write(readBuffer, 0, readLen);
}
}
}
}
}
}
ProgressMonitor使应用程序(尤其是面向用户)更易于集成Zip4j。显示进度非常有用(例如:更新进度栏,显示当前操作,显示正在处理的文件名等)。要使用ProgressMonitor,必须设置ZipFile.setRunInThread(true)。这将使对zip文件执行的所有操作均在后台线程中运行。然后,您可以访问ProgressMonitor Zipfile.getProgressMonitor()并获取当前正在执行的操作的详细信息以及完成的工作百分比等。以下是一个示例:
ZipFile zipFile = new ZipFile(generatedZipFile, PASSWORD);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
zipFile.setRunInThread(true);
zipFile.addFolder(new File("/some/folder"));
while (!progressMonitor.getState().equals(ProgressMonitor.State.READY)) {
System.out.println("Percentage done: " + progressMonitor.getPercentDone());
System.out.println("Current file: " + progressMonitor.getFileName());
System.out.println("Current task: " + progressMonitor.getCurrentTask());
Thread.sleep(100);
}
if (progressMonitor.getResult().equals(ProgressMonitor.Result.SUCCESS)) {
System.out.println("Successfully added folder to zip");
} else if (progressMonitor.getResult().equals(ProgressMonitor.Result.ERROR)) {
System.out.println("Error occurred. Error message: " + progressMonitor.getException().getMessage());
} else if (progressMonitor.getResult().equals(ProgressMonitor.Result.CANCELLED)) {
System.out.println("Task cancelled");
}
请注意,在上面的示例中,addFolder()几乎会立即将控件返回给调用方。然后,客户端代码可以执行循环,直到状态恢复为“就绪”为止,如上面的示例所示。
同样,ProgressMonitor可以与addFiles,removeFiles和等其他操作一起使用extractFiles。
/**
*
* 本地构建Zip文件(文件的Zip打包)
*
* 1. 创建单个文件(目录)进行zip打包(单参)
* 2. 将多个单文件(目录)添加到现有zip包中(多参):(目标zip,文件1,文件2...)
*
* @param o is String,File
* @return void
* @throws
* @Description
* @author Liruilong
* @Date 2020年08月19日 11:08:15
**/
public static void thisLocalityFileCreateZip(Object... o) {
// 这是异常处理的一个工具接口
exceptionUtil(() -> {
File f = null;
net.lingala.zip4j.ZipFile zipFile = null;
for (int i = 0; i < o.length; i++) {
if (o[i] instanceof String) {
f = new File((String) o[i]);
} else if (o[i] instanceof File) {
f = (File) o[i];
} else {
throw new IllegalArgumentException("参数异常");
}
if (i == 0) {
String fn = f.getName();
String fN = fn.substring(0, fn.indexOf(".") != -1 ? fn.indexOf(".") : fn.length());
String s = FILEPATH + fN + ".zip";
if (new File(s).exists()) {
cleanUtil(s);
}
zipFile = new net.lingala.zip4j.ZipFile(s);
zipFile.setRunInThread(true);
}
if (f.isDirectory()) {
zipFile.addFolder(f);
} else if (f.isFile()) {
zipFile.addFile(f);
}
}
}, "本地构建Zip文件异常");
}