package com.wj.dexknife.shell.utils;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by linchaolong on 2015/10/28.
*/
public class ZipHelper {
public static final String TAG = ZipHelper.class.getSimpleName();
public static InputStream getEntryInputStream(java.util.zip.ZipFile zip, String entryName){
if(zip == null){
return null;
}
try {
java.util.zip.ZipEntry entry = zip.getEntry(entryName);
if (entry == null) {
throw new FileNotFoundException("Cannot find "+entryName+" in zip file:"+zip.getName());
}
return zip.getInputStream(entry);
} catch (java.util.zip.ZipException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static boolean zip(File dir, File zipFile){
try {
if(!FileHelper.exists(dir)){
return false;
}
ZipFile zip = new ZipFile(zipFile);
// Initiate Zip Parameters which define various properties such
// as compression method, etc.
ZipParameters parameters = new ZipParameters();
// set compression method to store compression
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
// Set the compression level
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
// Sets the folder in the zip file to which these new files will be added.
// In this example, test2 is the folder to which these files will be added.
// Another example: if files were to be added to a directory test2/test3, then
// below statement should be parameters.setRootFolderInZip("test2/test3/");
//parameters.setRootFolderInZip("/test");
// Add folder to the zip file
zip.addFolder(dir, parameters);
return zipFile.exists();
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static boolean zip(List<File> files, File zipFile){
try {
ZipFile zip = new ZipFile(zipFile);
// Initiate Zip Parameters
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to deflate compression
// Set the compression level.
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
// Sets the folder in the zip file to which these new files will be added.
// In this example, test2 is the folder to which these files will be added.
// Another example: if files were to be added to a directory test2/test3, then
// below statement should be parameters.setRootFolderInZip("test2/test3/");
//parameters.setRootFolderInZip("/test");
// Now add files to the zip file
//zip.addFiles(new ArrayList(files), parameters);
for(File file : files){
if(file.exists()){
if(file.isDirectory()){
zip.addFolder(file,parameters);
}else{
zip.addFile(file,parameters);
}
}else{
Debug.e("zip error file not exits : " + file.getAbsolutePath());
}
}
zip.setRunInThread(false);
return zipFile.exists();
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static boolean zip(File[] files, File zipFile){
ArrayList<File> fileList = new ArrayList<>(files.length);
for(File file : files){
fileList.add(file);
}
return zip(fileList,zipFile);
}
public static boolean unzip(File zipFile, File outDir){
return unzip(zipFile, outDir, true);
}
public static boolean unzip(File zipFile, File outDir, boolean isClean){
try {
if(!FileHelper.exists(zipFile)){
return false;
}
ZipFile zip = new ZipFile(zipFile);
if(isClean && outDir.exists()){
FileHelper.delete(outDir);
}
zip.setRunInThread(false);
zip.extractAll(outDir.getPath());
return true;
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static abstract class FileFilter{
public abstract void handle(ZipFile zipFile, FileHeader fileHeader);
}
public static boolean hasFile(File zipFile, String fileName){
try {
if(!FileHelper.exists(zipFile)){
return false;
}
return hasFile(new ZipFile(zipFile),fileName);
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static boolean hasFile(ZipFile zip, String fileName){
try {
return zip.getFileHeader(fileName) != null;
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static void list(File zipFile, FileFilter filter){
try {
if(!FileHelper.exists(zipFile)){
return;
}
ZipFile zip = new ZipFile(zipFile);
zip.setRunInThread(false);
// Get the list of file headers from the zip file
List fileHeaderList = zip.getFileHeaders();
// Loop through the file headers
for (int i = 0; i < fileHeaderList.size(); i++) {
// Extract the file to the specified destination
filter.handle(zip, (FileHeader) fileHeaderList.get(i));
}
} catch (ZipException e) {
e.printStackTrace();
}
}
public static List<FileHeader> listForPattern(File zipFile, String regex){
List<FileHeader> list = new ArrayList<>();
Pattern p = Pattern.compile(regex);
// Pattern p = Pattern.compile("[^/]*\\.dex");
try {
if(!FileHelper.exists(zipFile)){
return new ArrayList<>(0);
}
ZipFile zip = new ZipFile( zipFile);
zip.setRunInThread(false);
// Get the list of file headers from the zip file
List fileHeaderList = zip.getFileHeaders();
// Loop through the file headers
for (int i = 0; i < fileHeaderList.size(); i++) {
// Extract the file to the specified destination
FileHeader fileHeader = (FileHeader) fileHeaderList.get(i);
Matcher matcher = p.matcher(fileHeader.getFileName());
if(matcher.matches()){
list.add(fileHeader);
}
}
return list;
} catch (ZipException e) {
e.printStackTrace();
}
return new ArrayList<>(0);
}
public static boolean unzip(ZipFile zip, FileHeader fileHeader, File destPath){
try {
zip.extractFile(fileHeader, destPath.getAbsolutePath());
return true;
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static boolean unzip(ZipFile zip, String fileName, File destPath){
try {
zip.extractFile(fileName, destPath.getAbsolutePath());
return true;
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static boolean removeFileFromZip(File zipFile, String fileName){
if(!FileHelper.exists(zipFile)){
return false;
}
try {
ZipFile zip = new ZipFile(zipFile);
LinkedList<FileHeader> removeList = new LinkedList<>();
for(Object fileHeaderObj : zip.getFileHeaders()){
FileHeader fileHeader = (FileHeader) fileHeaderObj;
if(fileHeader.getFileName().startsWith(fileName)){
removeList.add(fileHeader);
}
}
// Note: If this zip file is a split file then this method throws an exception as
// Zip Format Specification does not allow updating split zip files
// Please make sure that this zip file has more than one file to completely test
// this example
// Removal of a file from a zip file can be done in two ways:
//zip.removeFile(target);
for(FileHeader fileHeader : removeList){
zip.removeFile(fileHeader);
}
// if (zip.getFileHeaders() != null && zip.getFileHeaders().size() > 0) {
// zip.removeFile((FileHeader)zip.getFileHeaders().get(0));
// } else {
// Debug.d("This cannot be demonstrated as zip file does not have any files left");
// }
return true;
} catch (ZipException e) {
e.printStackTrace();
}
return false;
}
public static void merge(File f1, File f2, File outFile){
// init
File temp = new File(outFile.getParentFile(), FileHelper.getNoSuffixName(outFile));
FileHelper.cleanDirectory(temp);
if(f1.isDirectory()){
FileHelper.copyDir(f1,temp, false);
}else{
ZipHelper.unzip(f1,temp);
}
// merge
if(f2.isDirectory()){
FileHelper.copyDir(f2, temp, false);
}else{
// unzip
ZipHelper.unzip(f2,temp, false);
}
// zip
ZipHelper.zip(temp.listFiles(), outFile);
// clean
FileHelper.delete(temp);
}
}