#概要
Zip4jを使ってパスワード付ZIPファイルを作成するサンプルです。
対象のファイルがディレクトリの場合、サブディレクトリも含めて全てのファイルを、階層構造を維持したまま圧縮します。
#試した環境
- jdk 1.8.0_20
- zip4j 1.3.2
#サンプルコード
##ZipFileを使う
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import java.io.IOException;
public class ZipUtil {
private int compressionMethod = Zip4jConstants.COMP_DEFLATE;
private int compressionLevel = Zip4jConstants.DEFLATE_LEVEL_NORMAL;
private int encryptionMethod = Zip4jConstants.ENC_METHOD_STANDARD;
private int aesKeyStrength = Zip4jConstants.AES_STRENGTH_256;
public ZipUtil(){
}
public ZipUtil(int encryptionMethod, int aesKeyStrength) {
this.encryptionMethod = encryptionMethod;
this.aesKeyStrength = aesKeyStrength;
}
public void zip(String input, String output, String password)
throws ZipException, IOException {
zip(input, output, password, "");
}
public void zip(String input, String output, String password, String fileNameCharset)
throws ZipException, IOException {
ZipFile zipFile = new ZipFile(output);
// If the fileNameCharset is empty then charset is detected automatically
// Try with Cp850 and UTF8 or OS default
if (!fileNameCharset.isEmpty()) {
zipFile.setFileNameCharset(fileNameCharset);
}
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(compressionMethod);
parameters.setCompressionLevel(compressionLevel);
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(encryptionMethod);
parameters.setAesKeyStrength(aesKeyStrength);
parameters.setPassword(password);
File inputFile = new File(input);
if (inputFile.isDirectory()) {
zipFile.createZipFileFromFolder(inputFile, parameters, false, 0);
} else {
zipFile.addFile(inputFile, parameters);
}
}
public void unzip(String input, String output, String password) throws ZipException {
ZipFile zipFile = new ZipFile(input);
if (zipFile.isEncrypted()) {
zipFile.setPassword(password);
}
zipFile.extractAll(output);
}
}
##ZipOutputStreamを使う
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.ZipOutputStream;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import java.util.Arrays;
import java.util.LinkedList;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class ZipUtil {
private int compressionMethod = Zip4jConstants.COMP_DEFLATE;
private int compressionLevel = Zip4jConstants.DEFLATE_LEVEL_NORMAL;
private int encryptionMethod = Zip4jConstants.ENC_METHOD_STANDARD;
private int aesKeyStrength = Zip4jConstants.AES_STRENGTH_256;
public ZipUtil() {
}
public ZipUtil(int encryptionMethod, int aesKeyStrength) {
this.encryptionMethod = encryptionMethod;
this.aesKeyStrength = aesKeyStrength;
}
public void zip(String input, String output, String password)
throws ZipException, IOException, CloneNotSupportedException {
zip(input, output, password, "");
}
public void zip(String input, String output, String password, String fileNameCharset)
throws ZipException, IOException, CloneNotSupportedException {
ZipModel zipModel = new ZipModel();
// If the fileNameCharset is empty then charset is detected automatically
// Try with Cp850 and UTF8 or OS default
if (!fileNameCharset.isEmpty()) {
zipModel.setFileNameCharset(fileNameCharset);
}
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(compressionMethod);
parameters.setCompressionLevel(compressionLevel);
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(encryptionMethod);
parameters.setAesKeyStrength(aesKeyStrength);
parameters.setPassword(password);
parameters.setDefaultFolderPath(new File(input).getParent());
try (
ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(new File(output)), zipModel)
){
LinkedList<File> remained = new LinkedList();
remained.add(new File(input));
while (!remained.isEmpty()) {
File file = remained.pollFirst();
outputStream.putNextEntry(file, (ZipParameters)parameters.clone());
if (file.isDirectory()) {
remained.addAll(0, Arrays.asList(file.listFiles()));
} else {
try (
InputStream inputStream = new FileInputStream(file)
){
byte[] readBuff = new byte[4096];
int readLen = -1;
while ((readLen = inputStream.read(readBuff)) != -1) {
outputStream.write(readBuff, 0, readLen);
}
}
}
outputStream.closeEntry();
}
outputStream.finish();
}
}
public void unzip(String input, String output, String password) throws ZipException {
ZipFile zipFile = new ZipFile(input);
if (zipFile.isEncrypted()) {
zipFile.setPassword(password);
}
zipFile.extractAll(output);
}
}
#使用例
// Standard Enc
new ZipUtil().zip("/Users/hoge/file", "/Users/hoge/file.zip", "password");
// AES
new ZipUtil(Zip4jConstants.ENC_METHOD_AES, Zip4jConstants.AES_STRENGTH_256).zip("/Users/hoge/file", "/Users/hoge/file.zip", "password");
// Windowsで作成したファイルを圧縮
new ZipUtil().zip("/Users/hoge/file", "/Users/hoge/file.zip", "password", "windows-31j");
// Unzip
new ZipUtil().unzip("/Users/hoge/file.zip", "/Users/hoge/file", "password");
#補足
##ファイル名の文字コードについて
ZipModel.fileNameCharsetを指定している場合、指定された文字コードでエンコードする。
指定していない場合、自動判定。CP850, UTF8でエンコード、デコードしてみて元の文字列と一致するか判定する。どちらもあてはまらなければOSのデフォルトを使う。
ソースはこの辺
- HeaderWriter.writeLocalFileHeader
- Zip4jUtil.detectCharset
#参考