diff --git a/javase-tutorials/pom.xml b/javase-tutorials/pom.xml
index 0738465..4fb3bab 100644
--- a/javase-tutorials/pom.xml
+++ b/javase-tutorials/pom.xml
@@ -26,7 +26,7 @@
${project.basedir}/src/main/webapp/WEB-INF/lib/xxx.jar
-->
-
+
@@ -44,8 +44,8 @@
qrgen
1.3
-
-
+
+
net.coobird
@@ -53,7 +53,30 @@
0.4.7
+
+
+ joda-time
+ joda-time
+ 2.4
+
+
+
+
+ net.lingala.zip4j
+ zip4j
+ 1.3.2
+
+
+ org.apache.commons
+ commons-lang3
+ 3.3.2
+
+
+ junit
+ junit
+ 4.11
+
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/BinarySearch.java b/javase-tutorials/src/main/java/org/javase/tutorials/BinarySearch.java
index 9e1ca78..b1d0a78 100644
--- a/javase-tutorials/src/main/java/org/javase/tutorials/BinarySearch.java
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/BinarySearch.java
@@ -3,7 +3,7 @@ package org.javase.tutorials;
/**
* 二分法查找
- * @author welcome
+ * @author 冯靖
*
*/
public class BinarySearch {
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/SwapVar.java b/javase-tutorials/src/main/java/org/javase/tutorials/SwapVar.java
index 4e84208..2ff394f 100644
--- a/javase-tutorials/src/main/java/org/javase/tutorials/SwapVar.java
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/SwapVar.java
@@ -2,7 +2,7 @@ package org.javase.tutorials;
/**
* 交换两个数的值,不借助于第三个数
- * @author welcome
+ * @author 冯靖
*
*/
public class SwapVar {
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/jodatime/Jodatime.java b/javase-tutorials/src/main/java/org/javase/tutorials/jodatime/Jodatime.java
new file mode 100644
index 0000000..e102349
--- /dev/null
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/jodatime/Jodatime.java
@@ -0,0 +1,292 @@
+package org.javase.tutorials.jodatime;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeConstants;
+import org.joda.time.DateTimeZone;
+import org.joda.time.Duration;
+import org.joda.time.Interval;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalTime;
+import org.joda.time.Period;
+import org.joda.time.PeriodType;
+
+/**
+ * joda-time
+ * @author 冯靖
+ *
+ */
+public class Jodatime {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ getTime();
+ getTimeInfo();
+ convertJDK();
+ date();
+ }
+
+ private static void getTime(){
+
+ //方法一:取系统点间
+ DateTime dt1 = new DateTime();
+
+ print("方法一:取系统点间",dt1);
+
+ //方法二:通过java.util.Date对象生成
+ DateTime dt2 = new DateTime(new Date());
+
+ print("方法二:通过java.util.Date对象生成",dt2);
+
+ //方法三:指定年月日点分秒生成(参数依次是:年,月,日,时,分,秒,毫秒)
+ DateTime dt3 = new DateTime(2012, 5, 20, 13, 14, 0, 0);
+
+ print("方法三:指定年月日点分秒生成(参数依次是:年,月,日,时,分,秒,毫秒)",dt3);
+
+ //方法四:ISO8601形式生成
+ DateTime dt4 = new DateTime("2012-05-20");
+
+ print("方法四:ISO8601形式生成",dt4);
+
+ DateTime dt5 = new DateTime("2012-05-20T13:14:00");
+
+ print("方法四:ISO8601形式生成",dt5);
+
+ //只需要年月日的时候
+ LocalDate localDate = new LocalDate(2009, 9, 6);// September 6, 2009
+
+ System.out.println(localDate.toString("YYYY-MM-dd"));
+
+ //只需要时分秒毫秒的时候
+ LocalTime localTime = new LocalTime(13, 30, 26, 0);// 1:30:26PM
+
+ System.out.println(localTime.toString("hh:mm:ss.SSSa"));
+ }
+
+
+ private static void getTimeInfo(){
+
+ System.out.println("-------------获取当前时间-----------------");
+
+ String weekStr="";
+
+ DateTime dt = new DateTime();
+ //年
+ int year = dt.getYear();
+ //月
+ int month = dt.getMonthOfYear();
+ //日
+ int day = dt.getDayOfMonth();
+ //星期
+ int week = dt.getDayOfWeek();
+ //点
+ int hour = dt.getHourOfDay();
+ //分
+ int min = dt.getMinuteOfHour();
+ //秒
+ int sec = dt.getSecondOfMinute();
+ //毫秒
+ int msec = dt.getMillisOfSecond();
+
+ //星期
+ switch(week) {
+ case DateTimeConstants.SUNDAY:
+ weekStr = "星期日";
+ System.out.println(weekStr);
+ break;
+ case DateTimeConstants.MONDAY:
+ weekStr = "星期一";
+ System.out.println(weekStr);
+ break;
+ case DateTimeConstants.TUESDAY:
+ weekStr = "星期二";
+ System.out.println(weekStr);
+ break;
+ case DateTimeConstants.WEDNESDAY:
+ weekStr = "星期三";
+ System.out.println(weekStr);
+ break;
+ case DateTimeConstants.THURSDAY:
+ weekStr = "星期四";
+ System.out.println(weekStr);
+ break;
+ case DateTimeConstants.FRIDAY:
+ weekStr = "星期五";
+ System.out.println(weekStr);
+ break;
+ case DateTimeConstants.SATURDAY:
+ weekStr = "星期六";
+ System.out.println(weekStr);
+ break;
+ }
+
+ System.out.println(year + "/" + month + "/" + day + " " + hour + ":" + min + ":" + sec + ":" + msec + " " + weekStr);
+
+ }
+
+ /**
+ * 与jdk的时间转换
+ */
+ public static void convertJDK(){
+
+ System.out.println("-------------与jdk的时间转换-----------------");
+
+ DateTime dt = new DateTime();
+
+ //转换成java.util.Date对象
+
+ Date d1 = new Date(dt.getMillis());
+
+ Date d2 = dt.toDate();
+
+ //转换成java.util.Calendar对象
+ Calendar c1 = Calendar.getInstance();
+ c1.setTimeInMillis(dt.getMillis());
+
+ Calendar c2 = dt.toCalendar(Locale.getDefault());
+
+ }
+
+ /**
+ * 日期推算
+ */
+ public static void date(){
+
+ System.out.println("-------------日期推算-----------------");
+
+ DateTime dt = new DateTime();
+
+ print("今天",dt);
+
+ //昨天
+ DateTime yesterday = dt.minusDays(1);
+
+ print("昨天",yesterday);
+
+ //明天
+ DateTime tomorrow = dt.plusDays(1);
+
+ print("明天",tomorrow);
+
+ //1个月前
+ DateTime before1month = dt.minusMonths(1);
+
+ print("1个月前",before1month);
+
+ //3个月后
+ DateTime after3month = dt.plusMonths(3);
+
+ print("3个月后",after3month);
+
+ //2年前
+ DateTime before2year = dt.minusYears(2);
+
+ print("2年前",before2year);
+
+ //5年后
+ DateTime after5year = dt.plusYears(5);
+
+ print("5年后",after5year);
+
+ //特殊日期处理
+
+ //月末日期
+ DateTime lastday = dt.dayOfMonth().withMaximumValue();
+
+ print("月末日期",lastday);
+
+ //90天后那周的周一
+ DateTime firstday = dt.plusDays(90).dayOfWeek().withMinimumValue();
+
+ print("90天后那周的周一",firstday);
+
+ //时区
+ System.out.println("-------------时区-----------------");
+ //默认设置为日本时间
+ DateTimeZone.setDefault(DateTimeZone.forID("Asia/Tokyo"));
+
+ DateTime dt1 = new DateTime();
+
+ print("默认设置为日本时间",dt1);
+
+ //伦敦时间
+ DateTime dt2 = new DateTime(DateTimeZone.forID("Europe/London"));
+
+ print("伦敦时间",dt2);
+
+ //计算区间
+
+ System.out.println("-------------计算区间-----------------");
+
+ DateTime begin = new DateTime("2012-02-01");
+
+ DateTime end = new DateTime("2012-05-01");
+
+ //计算区间毫秒数
+ Duration d = new Duration(begin, end);
+ long time = d.getMillis();
+
+ System.out.println("计算区间毫秒数:"+time);
+
+ //计算区间天数
+ Period p = new Period(begin, end, PeriodType.days());
+ int days = p.getDays();
+
+ System.out.println("计算区间天数:"+days);
+
+ //计算特定日期是否在该区间内
+ Interval i = new Interval(begin, end);
+ boolean contained = i.contains(new DateTime("2012-03-01"));
+
+
+ //日期比较
+ System.out.println("-------------日期比较-----------------");
+
+ DateTime d1 = new DateTime("2012-02-01");
+ DateTime d2 = new DateTime("2012-05-01");
+
+ //和系统时间比
+ boolean b1 = d1.isAfterNow();//将来 以后
+ System.out.println("["+b1+"]"+d1.toString("yyyy-MM-dd")+"在"+dt.toString("yyyy-MM-dd")+"之前");
+ boolean b2 = d1.isBeforeNow();//以前 过去
+ System.out.println("["+b2+"]"+d1.toString("yyyy-MM-dd")+"在"+dt.toString("yyyy-MM-dd")+"之前");
+ boolean b3 = d1.isEqualNow();//与现在时间相同
+ System.out.println("["+b3+"]"+d1.toString("yyyy-MM-dd")+"与"+dt.toString("yyyy-MM-dd")+"相同");
+
+
+ //和其他日期比
+ boolean f1 = d1.isAfter(d2);
+ boolean f2 = d1.isBefore(d2);
+ boolean f3 = d1.isEqual(d2);
+
+
+ //格式化输出
+
+ System.out.println("-------------格式化输出-----------------");
+
+ DateTime dateTime = new DateTime();
+
+ String s1 = dateTime.toString("yyyy/MM/dd hh:mm:ss.SSSa");
+ String s2 = dateTime.toString("yyyy-MM-dd HH:mm:ss");
+ String s3 = dateTime.toString("EEEE dd MMMM, yyyy HH:mm:ssa");
+ String s4 = dateTime.toString("yyyy/MM/dd HH:mm ZZZZ");
+ String s5 = dateTime.toString("yyyy/MM/dd HH:mm Z");
+
+ System.out.println(s1);
+ System.out.println(s2);
+ System.out.println(s3);
+ System.out.println(s4);
+ System.out.println(s5);
+ }
+
+
+ private static void print(String tag,DateTime dateTime){
+ System.out.println(tag + ":" + dateTime.toString("yyyy-MM-dd HH:mm:ss"));
+ }
+
+}
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/qrcode/QRcode.java b/javase-tutorials/src/main/java/org/javase/tutorials/qrcode/QRcode.java
index 8223c4b..9f38e96 100644
--- a/javase-tutorials/src/main/java/org/javase/tutorials/qrcode/QRcode.java
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/qrcode/QRcode.java
@@ -1,10 +1,22 @@
package org.javase.tutorials.qrcode;
+import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.OutputStream;
+import javax.imageio.ImageIO;
+
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.LuminanceSource;
+import com.google.zxing.Result;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.QRCodeReader;
+
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
@@ -12,7 +24,7 @@ import net.glxn.qrgen.image.ImageType;
/**
* 使用qrgen生成二维码
*
- * @author welcome
+ * @author 冯靖
*
*/
public class QRcode {
@@ -22,9 +34,54 @@ public class QRcode {
*/
public static void main(String[] args) throws Exception{
- ByteArrayOutputStream out = QRCode.from("雪山飞鹄").withCharset("utf-8").withSize(480, 320).to(ImageType.PNG).stream();
+ File file = new File("target","qrcode.png");
+
+ String content = "http://aimeizi.net";
+
+ String charset = "utf-8";
+
+ int width = 320;
+
+ int height = 320;
+
+ generateCode(content,charset,width,height,file);
+
+ readCode(file);
+
+ }
+
+
+
+ /**
+ * 读取二维码
+ * @param file 二维码源
+ * @throws Exception
+ */
+ private static void readCode(File file) throws Exception{
+ BufferedImage encodedBufferedImage = ImageIO.read(file) ;
+ LuminanceSource source = new BufferedImageLuminanceSource(encodedBufferedImage);
+ Result result = new QRCodeReader().decode(new BinaryBitmap(new HybridBinarizer(source)));
+ System.out.println(result.getText());
+ }
- OutputStream outStream = new FileOutputStream(new File("target","qrcode.png"));
+
+
+
+ /**
+ * 生成二维码
+ * @param content 内容
+ * @param charset 字符编码
+ * @param width 宽
+ * @param height 高
+ * @param target 生成后写入路径
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private static void generateCode(String content,String charset,int width,int height,File target) throws FileNotFoundException,IOException {
+
+ ByteArrayOutputStream out = QRCode.from(content).withCharset(charset).withSize(width, height).to(ImageType.PNG).stream();
+
+ OutputStream outStream = new FileOutputStream(target);
outStream.write(out.toByteArray());
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/sort/Sort.java b/javase-tutorials/src/main/java/org/javase/tutorials/sort/Sort.java
index bbbcc48..859e4c1 100644
--- a/javase-tutorials/src/main/java/org/javase/tutorials/sort/Sort.java
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/sort/Sort.java
@@ -4,6 +4,8 @@ import java.util.Arrays;
/**
* 排序算法接口
+ * @author 冯靖
+ *
*/
public interface Sort {
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/sort/SortTest.java b/javase-tutorials/src/main/java/org/javase/tutorials/sort/SortTest.java
index 2ab89b6..e60b019 100644
--- a/javase-tutorials/src/main/java/org/javase/tutorials/sort/SortTest.java
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/sort/SortTest.java
@@ -6,7 +6,9 @@ import org.javase.tutorials.sort.Sort.SortUtil;
import org.javase.tutorials.sort.Sort.Sorts;
/**
- * 冒择入希快归堆:常用排序算法
+ * 常用排序算法
+ * @author 冯靖
+ *
*/
public class SortTest {
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/thumbnailator/Thumbnailator.java b/javase-tutorials/src/main/java/org/javase/tutorials/thumbnailator/Thumbnailator.java
index cfd62a9..861eb00 100644
--- a/javase-tutorials/src/main/java/org/javase/tutorials/thumbnailator/Thumbnailator.java
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/thumbnailator/Thumbnailator.java
@@ -1,17 +1,227 @@
package org.javase.tutorials.thumbnailator;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import javax.imageio.ImageIO;
+
+import net.coobird.thumbnailator.Thumbnails;
+import net.coobird.thumbnailator.geometry.Positions;
+
+import org.junit.Test;
+
/**
* Java缩略图生成类库
+ * @see https://code.google.com/p/thumbnailator/wiki/Examples
+ * @author 冯靖
+ *
+ */
+/**
* @author welcome
*
*/
public class Thumbnailator {
- /**
- * @param args
- */
- public static void main(String[] args) {
-
- }
+ /**
+ * 指定大小进行缩放
+ */
+ @Test
+ public void example1() throws Exception{
+ //size(宽度, 高度)
+ /*
+ * 若图片横比200小,高比300小,不变
+ * 若图片横比200小,高比300大,高缩小到300,图片比例不变
+ * 若图片横比200大,高比300小,横缩小到200,图片比例不变
+ * 若图片横比200大,高比300大,图片按比例缩小,横为200或高为300
+ */
+ Thumbnails.of("src/main/resources/example.jpg").size(200, 300).toFile("src/main/resources/200x300.jpg");
+ Thumbnails.of("src/main/resources/example.jpg").size(2560, 2048).toFile("src/main/resources/2560x2048.jpg");
+
+ }
+
+
+ /**
+ * 按照比例进行缩放
+ */
+ @Test
+ public void example2() throws Exception{
+ //scale(比例)
+ Thumbnails.of("src/main/resources/example.jpg")
+ .scale(0.25f)
+ //.outputQuality(0.8)
+ .toFile("src/main/resources/25%.jpg");
+
+ Thumbnails.of("src/main/resources/example.jpg")
+ .scale(1.10f)
+ //.outputQuality(0.8)
+ .toFile("src/main/resources/110%.jpg");
+
+ }
+
+
+ /**
+ * 不按照比例,指定大小进行缩放
+ */
+ @Test
+ public void example3() throws Exception{
+ //keepAspectRatio(false) 默认是按照比例缩放的
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(200, 200)
+ .keepAspectRatio(false)
+ .toFile("src/main/resources/200x200.jpg");
+ }
+
+
+ /**
+ * 旋转
+ */
+ @Test
+ public void example4() throws Exception{
+ //rotate(角度),正数:顺时针 负数:逆时针
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .rotate(90)
+ .toFile("src/main/resources/rotate+90.jpg");
+
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .rotate(-90)
+ .toFile("src/main/resources/rotate-90.jpg");
+
+ }
+
+
+ /**
+ * 水印
+ */
+ @Test
+ public void example5() throws Exception{
+ //watermark(位置,水印图,透明度)
+
+ //左上角
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .watermark(Positions.TOP_LEFT, ImageIO.read(new File("src/main/resources/watermark.png")), 0.5f)
+ .outputQuality(0.8f)
+ .toFile("src/main/resources/a380_watermark_top_left.jpg");
+
+ //左下角
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .watermark(Positions.BOTTOM_LEFT, ImageIO.read(new File("src/main/resources/watermark.png")), 0.5f)
+ .outputQuality(0.8f)
+ .toFile("src/main/resources/a380_watermark_bottom_left.jpg");
+
+
+ //右上角
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .watermark(Positions.TOP_RIGHT, ImageIO.read(new File("src/main/resources/watermark.png")), 0.5f)
+ .outputQuality(0.8f)
+ .toFile("src/main/resources/a380_watermark_top_right.jpg");
+
+
+ //右下角
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("src/main/resources/watermark.png")), 0.5f)
+ .outputQuality(0.8f)
+ .toFile("src/main/resources/a380_watermark_bottom_right.jpg");
+
+ //局中
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .watermark(Positions.CENTER, ImageIO.read(new File("src/main/resources/watermark.png")), 0.5f)
+ .outputQuality(0.8f)
+ .toFile("src/main/resources/a380_watermark_center.jpg");
+
+ }
+
+
+ /**
+ * 裁剪
+ */
+ @Test
+ public void example6() throws Exception{
+ //sourceRegion()
+ //图片中心400*400的区域
+ Thumbnails.of("src/main/resources/example.jpg")
+ .sourceRegion(Positions.CENTER, 400,400)
+ .size(200, 200)
+ .keepAspectRatio(false)
+ .toFile("src/main/resources/a380_region_center.jpg");
+
+ //图片右下400*400的区域
+ Thumbnails.of("src/main/resources/example.jpg")
+ .sourceRegion(Positions.BOTTOM_RIGHT, 400,400)
+ .size(200, 200)
+ .keepAspectRatio(false)
+ .toFile("src/main/resources/a380_region_bootom_right.jpg");
+
+ //指定坐标
+ Thumbnails.of("src/main/resources/example.jpg")
+ .sourceRegion(300, 250, 260, 260)
+ .size(200, 200)
+ .keepAspectRatio(false)
+ .toFile("src/main/resources/a380_region_coord.jpg");
+
+ }
+
+
+ /**
+ * 转化图像格式
+ */
+ @Test
+ public void example7() throws Exception{
+ //outputFormat(图像格式)
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .outputFormat("png")
+ .toFile("src/main/resources/a380_1280x1024.png");
+
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .outputFormat("gif")
+ .toFile("src/main/resources/a380_1280x1024.gif");
+ }
+
+
+
+ /**
+ * 输出到OutputStream
+ */
+ @Test
+ public void example8() throws Exception{
+ //toOutputStream(流对象)
+ OutputStream os = new FileOutputStream("src/main/resources/a380_1280x1024_OutputStream.png");
+ Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .toOutputStream(os);
+
+ }
+
+
+ /**
+ * 输出到BufferedImage
+ */
+ @Test
+ public void example9() throws Exception{
+ //asBufferedImage() 返回BufferedImage
+ BufferedImage thumbnail = Thumbnails.of("src/main/resources/example.jpg")
+ .size(1280, 1024)
+ .asBufferedImage();
+ ImageIO.write(thumbnail, "jpg", new File("src/main/resources/a380_1280x1024_BufferedImage.jpg"));
+
+ }
+
+
+
+
+
+
+
+
}
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/zip4j/CompressUtil.java b/javase-tutorials/src/main/java/org/javase/tutorials/zip4j/CompressUtil.java
new file mode 100644
index 0000000..d201426
--- /dev/null
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/zip4j/CompressUtil.java
@@ -0,0 +1,329 @@
+package org.javase.tutorials.zip4j;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+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;
+
+/**
+ * ZIP压缩文件操作工具类 支持密码,默认采用UTF-8编码 依赖zip4j开源项目(http://www.lingala.net/zip4j/)
+ * 版本1.3.2
+ *
+ * @author ninemax
+ */
+public class CompressUtil {
+
+ /**
+ * 使用给定密码解压指定的ZIP压缩文件到指定目录
+ *
+ * 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
+ *
+ * @param zip
+ * 指定的ZIP压缩文件
+ * @param dest
+ * 解压目录
+ * @param passwd
+ * ZIP文件的密码
+ * @return 解压后文件数组
+ * @throws ZipException
+ * 压缩文件有损坏或者解压缩失败抛出
+ */
+ public static File[] unzip(String zip, String dest, String passwd)
+ throws ZipException {
+ File zipFile = new File(zip);
+ return unzip(zipFile, dest, passwd, null);
+ }
+
+ /**
+ * 使用给定密码解压指定的ZIP压缩文件到当前目录
+ *
+ * @param zip
+ * 指定的ZIP压缩文件
+ * @param passwd
+ * ZIP文件的密码
+ * @return 解压后文件数组
+ * @throws ZipException
+ * 压缩文件有损坏或者解压缩失败抛出
+ */
+ public static File[] unzip(String zip, String passwd) throws ZipException {
+ File zipFile = new File(zip);
+ File parentDir = zipFile.getParentFile();
+ return unzip(zipFile, parentDir.getAbsolutePath(), passwd, null);
+ }
+
+ /**
+ * 使用给定密码解压指定的ZIP压缩文件到指定目录
+ *
+ * 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
+ *
+ * @param zip
+ * 指定的ZIP压缩文件
+ * @param dest
+ * 解压目录
+ * @param passwd
+ * ZIP文件的密码
+ * @param charset
+ * ZIP文件的编码
+ * @return 解压后文件数组
+ * @throws ZipException
+ * 压缩文件有损坏或者解压缩失败抛出
+ */
+ public static File[] unzip(File zipFile, String dest, String passwd,
+ String charset) throws ZipException {
+ ZipFile zFile = new ZipFile(zipFile);
+ if (null != charset || !"".equals(charset)) {
+ zFile.setFileNameCharset(charset);
+ }
+ if (!zFile.isValidZipFile()) {
+ throw new ZipException("压缩文件不合法,可能被损坏.");
+ }
+ File destDir = new File(dest);
+ if (destDir.isDirectory() && !destDir.exists()) {
+ destDir.mkdir();
+ }
+ if (zFile.isEncrypted()) {
+ zFile.setPassword(passwd.toCharArray());
+ }
+ zFile.extractAll(dest);
+
+ List headerList = zFile.getFileHeaders();
+ List extractedFileList = new ArrayList();
+ for (FileHeader fileHeader : headerList) {
+ if (!fileHeader.isDirectory()) {
+ extractedFileList.add(new File(destDir, fileHeader
+ .getFileName()));
+ }
+ }
+ File[] extractedFiles = new File[extractedFileList.size()];
+ extractedFileList.toArray(extractedFiles);
+ return extractedFiles;
+ }
+
+ /**
+ * 压缩指定文件到当前文件夹
+ *
+ * @param src
+ * 要压缩的指定文件
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src) {
+ return zip(src, null);
+ }
+
+ /**
+ * 使用给定密码压缩指定文件或文件夹到当前目录
+ *
+ * @param src
+ * 要压缩的文件
+ * @param passwd
+ * 压缩使用的密码
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src, String passwd) {
+ return zip(src, null, passwd);
+ }
+
+ /**
+ * 使用给定密码压缩指定文件或文件夹到当前目录
+ *
+ * @param src
+ * 要压缩的文件
+ * @param dest
+ * 压缩文件存放路径
+ * @param passwd
+ * 压缩使用的密码
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src, String dest, String passwd) {
+ return zip(src, dest, true, passwd);
+ }
+
+ /**
+ * 使用给定密码压缩指定文件或文件夹到指定位置.
+ *
+ * dest可传最终压缩文件存放的绝对路径,也可以传存放目录,也可以传null或者"".
+ * 如果传null或者""则将压缩文件存放在当前目录,即跟源文件同目录,压缩文件名取源文件名,以.zip为后缀;
+ * 如果以路径分隔符(File.separator)结尾,则视为目录,压缩文件名取源文件名,以.zip为后缀,否则视为文件名.
+ *
+ * @param src
+ * 要压缩的文件或文件夹路径
+ * @param dest
+ * 压缩文件存放路径
+ * @param isCreateDir
+ * 是否在压缩文件里创建目录,仅在压缩文件为目录时有效.
+ * 如果为false,将直接压缩目录下文件到压缩文件.
+ * @param passwd
+ * 压缩使用的密码
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src, String dest, boolean isCreateDir,
+ String passwd) {
+ File srcFile = new File(src);
+ dest = buildDestinationZipFilePath(srcFile, dest);
+ ZipParameters parameters = new ZipParameters();
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // 压缩方式
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); // 压缩级别
+ if (!StringUtils.isEmpty(passwd)) {
+ parameters.setEncryptFiles(true);
+ parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD); // 加密方式
+ parameters.setPassword(passwd.toCharArray());
+ }
+ try {
+ ZipFile zipFile = new ZipFile(dest);
+ if (srcFile.isDirectory()) {
+ // 如果不创建目录的话,将直接把给定目录下的文件压缩到压缩文件,即没有目录结构
+ if (!isCreateDir) {
+ File[] subFiles = srcFile.listFiles();
+ ArrayList temp = new ArrayList();
+ Collections.addAll(temp, subFiles);
+ zipFile.addFiles(temp, parameters);
+ return dest;
+ }
+ zipFile.addFolder(srcFile, parameters);
+ } else {
+ zipFile.addFile(srcFile, parameters);
+ }
+ return dest;
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 构建压缩文件存放路径,如果不存在将会创建 传入的可能是文件名或者目录,也可能不传,此方法用以转换最终压缩文件的存放路径
+ *
+ * @param srcFile
+ * 源文件
+ * @param destParam
+ * 压缩目标路径
+ * @return 正确的压缩文件存放路径
+ */
+ private static String buildDestinationZipFilePath(File srcFile,
+ String destParam) {
+ if (StringUtils.isEmpty(destParam)) {
+ if (srcFile.isDirectory()) {
+ destParam = srcFile.getParent() + File.separator
+ + srcFile.getName() + ".zip";
+ } else {
+ String fileName = srcFile.getName().substring(0,
+ srcFile.getName().lastIndexOf("."));
+ destParam = srcFile.getParent() + File.separator + fileName
+ + ".zip";
+ }
+ } else {
+ createDestDirectoryIfNecessary(destParam); // 在指定路径不存在的情况下将其创建出来
+ if (destParam.endsWith(File.separator)) {
+ String fileName = "";
+ if (srcFile.isDirectory()) {
+ fileName = srcFile.getName();
+ } else {
+ fileName = srcFile.getName().substring(0,
+ srcFile.getName().lastIndexOf("."));
+ }
+ destParam += fileName + ".zip";
+ }
+ }
+ return destParam;
+ }
+
+ /**
+ * 在必要的情况下创建压缩文件存放目录,比如指定的存放路径并没有被创建
+ *
+ * @param destParam
+ * 指定的存放路径,有可能该路径并没有被创建
+ */
+ private static void createDestDirectoryIfNecessary(String destParam) {
+ File destDir = null;
+ if (destParam.endsWith(File.separator)) {
+ destDir = new File(destParam);
+ } else {
+ destDir = new File(destParam.substring(0,
+ destParam.lastIndexOf(File.separator)));
+ }
+ if (!destDir.exists()) {
+ destDir.mkdirs();
+ }
+ }
+
+ /**
+ * 删除压缩文件中的目录
+ *
+ * @param file
+ * 目标zip文件
+ * @param removeDir
+ * 要移除的目录
+ * @param charset
+ * 编码
+ * @throws ZipException
+ */
+ @SuppressWarnings("rawtypes")
+ private static void removeDirFromZipArchive(String file, String removeDir,
+ String charset) throws ZipException {
+ // 创建ZipFile并设置编码
+ ZipFile zipFile = new ZipFile(file);
+
+ if (null != charset || !"".equals(charset)) {
+ zipFile.setFileNameCharset(charset);
+ }
+
+ // 给要删除的目录加上路径分隔符
+ if (!removeDir.endsWith(File.separator))
+ removeDir += File.separator;
+
+ // 如果目录不存在, 直接返回
+ FileHeader dirHeader = zipFile.getFileHeader(removeDir);
+ if (null == dirHeader)
+ return;
+
+ // 遍历压缩文件中所有的FileHeader, 将指定删除目录下的子文件名保存起来
+ List headersList = zipFile.getFileHeaders();
+ List removeHeaderNames = new ArrayList();
+ for (int i = 0, len = headersList.size(); i < len; i++) {
+ FileHeader subHeader = (FileHeader) headersList.get(i);
+ if (subHeader.getFileName().startsWith(dirHeader.getFileName())
+ && !subHeader.getFileName().equals(dirHeader.getFileName())) {
+ removeHeaderNames.add(subHeader.getFileName());
+ }
+ }
+ // 遍历删除指定目录下的所有子文件, 最后删除指定目录(此时已为空目录)
+ for (String headerNameString : removeHeaderNames) {
+ zipFile.removeFile(headerNameString);
+ }
+ zipFile.removeFile(dirHeader);
+ }
+
+ /**
+ * 打印zip文件信息
+ *
+ * @param path
+ */
+ public static void printZipInfo(String path) {
+ try {
+ ZipFile zipFile = new ZipFile(path);
+ List fileHeaderList = zipFile.getFileHeaders();
+ for (int i = 0; i < fileHeaderList.size(); i++) {
+ FileHeader fileHeader = (FileHeader) fileHeaderList.get(i);
+ // FileHeader包含zip文件中对应文件的很多属性
+ System.out.println("****File Details for: " + fileHeader.getFileName() + "*****");
+ System.out.println("文件名: " + fileHeader.getFileName());
+ System.out.println("是否为目录: " + fileHeader.isDirectory());
+ System.out.println("压缩后大小: " + fileHeader.getCompressedSize());
+ System.out.println("未压缩大小: " + fileHeader.getUncompressedSize());
+ System.out.println("************************************************************");
+ }
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/javase-tutorials/src/main/java/org/javase/tutorials/zip4j/Zip4j.java b/javase-tutorials/src/main/java/org/javase/tutorials/zip4j/Zip4j.java
new file mode 100644
index 0000000..d90c8e5
--- /dev/null
+++ b/javase-tutorials/src/main/java/org/javase/tutorials/zip4j/Zip4j.java
@@ -0,0 +1,215 @@
+package org.javase.tutorials.zip4j;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+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 org.junit.Before;
+import org.junit.Test;
+
+/**
+ * 使用zip4j压缩或解压文件
+ * @author 冯靖
+ *
+ */
+public class Zip4j {
+
+
+ @Before
+ public void setup() throws Exception{
+ ZipFile zipFile = new ZipFile("src/main/resources/AddFilesDeflateComp.zip");
+ if(zipFile.getFile().exists()){
+ zipFile.getFile().delete();
+ }
+ }
+
+
+ /**
+ * 示例1 创建压缩包添加文件到压缩包中(未设置加密)
+ */
+ @Test
+ public void example1(){
+ try {
+
+ ZipFile zipFile = new ZipFile("src/main/resources/AddFilesDeflateComp.zip");
+
+ ArrayList filesToAdd = new ArrayList();
+ filesToAdd.add(new File("src/main/resources/sample.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j-1.3.2.jar"));
+
+ ZipParameters parameters = new ZipParameters();
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to deflate compression
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+ zipFile.addFiles(filesToAdd, parameters);
+
+ CompressUtil.printZipInfo("src/main/resources/AddFilesDeflateComp.zip");
+
+
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * 示例2 创建压缩包添加文件到指定目录中进行压缩
+ */
+ @Test
+ public void example2(){
+ try {
+ ZipFile zipFile = new ZipFile("src/main/resources/AddFilesDeflateComp.zip");
+ ArrayList filesToAdd = new ArrayList();
+ filesToAdd.add(new File("src/main/resources/sample.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j-1.3.2.jar"));
+
+ ZipParameters parameters = new ZipParameters();
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+ parameters.setRootFolderInZip("target/");
+
+ zipFile.addFiles(filesToAdd, parameters);
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 示例3 添加文件夹到压缩包中
+ */
+ @Test
+ public void example3(){
+ try {
+
+ ZipFile zipFile = new ZipFile("src/main/resources/AddFolder.zip");
+ String folderToAdd = "src/main/resources";
+
+ ZipParameters parameters = new ZipParameters();
+
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+ zipFile.addFolder(folderToAdd, parameters);
+
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 示例4 创建加密压缩包
+ */
+ @Test
+ public void example4(){
+ try {
+ ZipFile zipFile = new ZipFile("src/main/resources/AddFilesWithAESZipEncryption.zip");
+
+ ArrayList filesToAdd = new ArrayList();
+ filesToAdd.add(new File("src/main/resources/sample.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j-1.3.2.jar"));
+
+ ZipParameters parameters = new ZipParameters();
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+ parameters.setEncryptFiles(true);
+
+ parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
+
+
+ parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
+ parameters.setPassword("123456");
+
+ zipFile.addFiles(filesToAdd, parameters);
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 示例5 创建分卷压缩包
+ */
+ @Test
+ public void example5(){
+ try {
+
+ ZipFile zipFile = new ZipFile("src/main/resources/CreateSplitZipFile.zip");
+
+ ArrayList filesToAdd = new ArrayList();
+ filesToAdd.add(new File("src/main/resources/sample.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j.txt"));
+ filesToAdd.add(new File("src/main/resources/zip4j-1.3.2.jar"));
+
+ ZipParameters parameters = new ZipParameters();
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+
+ zipFile.createZipFile(filesToAdd, parameters, true, 65536);
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 示例6 通过流的方式添加文件到压缩包中
+ */
+ @Test
+ public void example6(){
+ InputStream is = null;
+
+ try {
+ ZipFile zipFile = new ZipFile("src/main/resources/AddStreamToZip.zip");
+
+ ZipParameters parameters = new ZipParameters();
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+ parameters.setFileNameInZip("sample.txt");
+ parameters.setSourceExternalStream(true);
+
+ is = new FileInputStream("src/main/resources/sample.txt");
+ zipFile.addStream(is, parameters);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+
+ /**
+ * 示例7 解压压缩文件
+ */
+ @Test
+ public void example7(){
+
+ example4();
+
+ try {
+ ZipFile zipFile = new ZipFile("src/main/resources/AddFilesWithAESZipEncryption.zip");
+ if (zipFile.isEncrypted()) {
+ // if yes, then set the password for the zip file
+ zipFile.setPassword("123456");
+ zipFile.extractAll("src/main/resources/zipfile");
+ }
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/javase-tutorials/src/main/resources/example.jpg b/javase-tutorials/src/main/resources/example.jpg
new file mode 100644
index 0000000..f213a75
Binary files /dev/null and b/javase-tutorials/src/main/resources/example.jpg differ
diff --git a/javase-tutorials/src/main/resources/sample.txt b/javase-tutorials/src/main/resources/sample.txt
new file mode 100644
index 0000000..325313f
--- /dev/null
+++ b/javase-tutorials/src/main/resources/sample.txt
@@ -0,0 +1,51 @@
+ZIP4J 是一个支持处理ZIP文件的开源库
+支持创建,修改,添加,删除,解压 压缩文件
+支持读/写密码保护
+支持AES加密 128/256
+支持标准ZIP加密
+支持进度监视器
+自持Unicode 文件名
+支持创建分卷压缩文件
+支持将文件添加到压缩包中但不进行压缩
+
+
+Create, Add, Extract, Update, Remove files from a Zip file
+针对ZIP压缩文件创建、添加、抽出、更新和移除文件
+Read/Write password protected Zip files
+(读写有密码保护的Zip文件)
+Supports AES 128/256 Encryption
+(支持AES 128/256算法加密)
+Supports Standard Zip Encryption
+(支持标准Zip算法加密)
+Supports Zip64 format
+(支持zip64格式)
+Supports Store (No Compression) and Deflate compression method
+(支持Store(非压缩)和Deflate压缩方法---不太明白)
+Create or extract files from Split Zip files (Ex: z01, z02,...zip)
+(针对分块zip文件创建和抽出文件)
+Supports Unicode file names
+(支持Unicode编码文件名)
+Progress Monitor
+(进度监控)
+
+压缩效率
+
+ ZIP4J提供5中压缩算法:
+
+ DEFLATE_LEVEL_FASTEST
+ DEFLATE_LEVEL_FASTEST
+ DEFLATE_LEVEL_NORMAL
+ DEFLATE_LEVEL_MAXIMUM
+ DEFLATE_LEVEL_ULTRA
+ 根据API提供的几种不同压缩级别进行测试(文件夹压缩),测试结果如下:
+
+ 一个180M的文件夹压缩后
+
+ WinRAR 30秒 - 78.7 MB ;
+ NORMAL - 18 秒 91.2 MB ;
+ FAST 13秒 -93.1 MB;
+ FASTEST - 最快速10 秒94.7 MB
+ MAXIMUM 23 秒 - 90.7 MB;
+ ULTRA -50 90.6 MB
+
+ZIP4J 项目地址为 :http://www.lingala.net/zip4j/
\ No newline at end of file
diff --git a/javase-tutorials/src/main/resources/watermark.png b/javase-tutorials/src/main/resources/watermark.png
new file mode 100644
index 0000000..c9c22b3
Binary files /dev/null and b/javase-tutorials/src/main/resources/watermark.png differ
diff --git a/javase-tutorials/src/main/resources/zip4j-1.3.2.jar b/javase-tutorials/src/main/resources/zip4j-1.3.2.jar
new file mode 100644
index 0000000..dcdf85e
Binary files /dev/null and b/javase-tutorials/src/main/resources/zip4j-1.3.2.jar differ
diff --git a/javase-tutorials/src/main/resources/zip4j.txt b/javase-tutorials/src/main/resources/zip4j.txt
new file mode 100644
index 0000000..72f8529
--- /dev/null
+++ b/javase-tutorials/src/main/resources/zip4j.txt
@@ -0,0 +1,262 @@
+package org.javase.tutorials.zip4j;
+
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+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;
+
+/**
+ * ZIP压缩文件操作工具类
+ * 支持密码,默认采用UTF-8编码
+ * 依赖zip4j开源项目(http://www.lingala.net/zip4j/)
+ * 版本1.3.2
+ * @author ninemax
+ */
+public class CompressUtil {
+
+ /**
+ * 使用给定密码解压指定的ZIP压缩文件到指定目录
+ *
+ * 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
+ * @param zip 指定的ZIP压缩文件
+ * @param dest 解压目录
+ * @param passwd ZIP文件的密码
+ * @return 解压后文件数组
+ * @throws ZipException 压缩文件有损坏或者解压缩失败抛出
+ */
+ public static File [] unzip(String zip, String dest, String passwd) throws ZipException {
+ File zipFile = new File(zip);
+ return unzip(zipFile, dest, passwd);
+ }
+
+ /**
+ * 使用给定密码解压指定的ZIP压缩文件到当前目录
+ * @param zip 指定的ZIP压缩文件
+ * @param passwd ZIP文件的密码
+ * @return 解压后文件数组
+ * @throws ZipException 压缩文件有损坏或者解压缩失败抛出
+ */
+ public static File [] unzip(String zip, String passwd) throws ZipException {
+ File zipFile = new File(zip);
+ File parentDir = zipFile.getParentFile();
+ return unzip(zipFile, parentDir.getAbsolutePath(), passwd);
+ }
+
+ /**
+ * 使用给定密码解压指定的ZIP压缩文件到指定目录
+ *
+ * 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
+ * @param zip 指定的ZIP压缩文件
+ * @param dest 解压目录
+ * @param passwd ZIP文件的密码
+ * @return 解压后文件数组
+ * @throws ZipException 压缩文件有损坏或者解压缩失败抛出
+ */
+ public static File [] unzip(File zipFile, String dest, String passwd) throws ZipException {
+ ZipFile zFile = new ZipFile(zipFile);
+ zFile.setFileNameCharset("GBK");
+ if (!zFile.isValidZipFile()) {
+ throw new ZipException("压缩文件不合法,可能被损坏.");
+ }
+ File destDir = new File(dest);
+ if (destDir.isDirectory() && !destDir.exists()) {
+ destDir.mkdir();
+ }
+ if (zFile.isEncrypted()) {
+ zFile.setPassword(passwd.toCharArray());
+ }
+ zFile.extractAll(dest);
+
+ List headerList = zFile.getFileHeaders();
+ List extractedFileList = new ArrayList();
+ for(FileHeader fileHeader : headerList) {
+ if (!fileHeader.isDirectory()) {
+ extractedFileList.add(new File(destDir,fileHeader.getFileName()));
+ }
+ }
+ File [] extractedFiles = new File[extractedFileList.size()];
+ extractedFileList.toArray(extractedFiles);
+ return extractedFiles;
+ }
+
+ /**
+ * 压缩指定文件到当前文件夹
+ * @param src 要压缩的指定文件
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src) {
+ return zip(src,null);
+ }
+
+ /**
+ * 使用给定密码压缩指定文件或文件夹到当前目录
+ * @param src 要压缩的文件
+ * @param passwd 压缩使用的密码
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src, String passwd) {
+ return zip(src, null, passwd);
+ }
+
+ /**
+ * 使用给定密码压缩指定文件或文件夹到当前目录
+ * @param src 要压缩的文件
+ * @param dest 压缩文件存放路径
+ * @param passwd 压缩使用的密码
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src, String dest, String passwd) {
+ return zip(src, dest, true, passwd);
+ }
+
+ /**
+ * 使用给定密码压缩指定文件或文件夹到指定位置.
+ *
+ * dest可传最终压缩文件存放的绝对路径,也可以传存放目录,也可以传null或者"".
+ * 如果传null或者""则将压缩文件存放在当前目录,即跟源文件同目录,压缩文件名取源文件名,以.zip为后缀;
+ * 如果以路径分隔符(File.separator)结尾,则视为目录,压缩文件名取源文件名,以.zip为后缀,否则视为文件名.
+ * @param src 要压缩的文件或文件夹路径
+ * @param dest 压缩文件存放路径
+ * @param isCreateDir 是否在压缩文件里创建目录,仅在压缩文件为目录时有效.
+ * 如果为false,将直接压缩目录下文件到压缩文件.
+ * @param passwd 压缩使用的密码
+ * @return 最终的压缩文件存放的绝对路径,如果为null则说明压缩失败.
+ */
+ public static String zip(String src, String dest, boolean isCreateDir, String passwd) {
+ File srcFile = new File(src);
+ dest = buildDestinationZipFilePath(srcFile, dest);
+ ZipParameters parameters = new ZipParameters();
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // 压缩方式
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); // 压缩级别
+ if (!StringUtils.isEmpty(passwd)) {
+ parameters.setEncryptFiles(true);
+ parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD); // 加密方式
+ parameters.setPassword(passwd.toCharArray());
+ }
+ try {
+ ZipFile zipFile = new ZipFile(dest);
+ if (srcFile.isDirectory()) {
+ // 如果不创建目录的话,将直接把给定目录下的文件压缩到压缩文件,即没有目录结构
+ if (!isCreateDir) {
+ File [] subFiles = srcFile.listFiles();
+ ArrayList temp = new ArrayList();
+ Collections.addAll(temp, subFiles);
+ zipFile.addFiles(temp, parameters);
+ return dest;
+ }
+ zipFile.addFolder(srcFile, parameters);
+ } else {
+ zipFile.addFile(srcFile, parameters);
+ }
+ return dest;
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 构建压缩文件存放路径,如果不存在将会创建
+ * 传入的可能是文件名或者目录,也可能不传,此方法用以转换最终压缩文件的存放路径
+ * @param srcFile 源文件
+ * @param destParam 压缩目标路径
+ * @return 正确的压缩文件存放路径
+ */
+ private static String buildDestinationZipFilePath(File srcFile,String destParam) {
+ if (StringUtils.isEmpty(destParam)) {
+ if (srcFile.isDirectory()) {
+ destParam = srcFile.getParent() + File.separator + srcFile.getName() + ".zip";
+ } else {
+ String fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf("."));
+ destParam = srcFile.getParent() + File.separator + fileName + ".zip";
+ }
+ } else {
+ createDestDirectoryIfNecessary(destParam); // 在指定路径不存在的情况下将其创建出来
+ if (destParam.endsWith(File.separator)) {
+ String fileName = "";
+ if (srcFile.isDirectory()) {
+ fileName = srcFile.getName();
+ } else {
+ fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf("."));
+ }
+ destParam += fileName + ".zip";
+ }
+ }
+ return destParam;
+ }
+
+ /**
+ * 在必要的情况下创建压缩文件存放目录,比如指定的存放路径并没有被创建
+ * @param destParam 指定的存放路径,有可能该路径并没有被创建
+ */
+ private static void createDestDirectoryIfNecessary(String destParam) {
+ File destDir = null;
+ if (destParam.endsWith(File.separator)) {
+ destDir = new File(destParam);
+ } else {
+ destDir = new File(destParam.substring(0, destParam.lastIndexOf(File.separator)));
+ }
+ if (!destDir.exists()) {
+ destDir.mkdirs();
+ }
+ }
+
+
+ /**
+ * 删除压缩文件中的目录
+ * @param file 目标zip文件
+ * @param removeDir 要移除的目录
+ * @throws ZipException
+ */
+ @SuppressWarnings("rawtypes")
+ private static void removeDirFromZipArchive(String file, String removeDir) throws ZipException {
+ // 创建ZipFile并设置编码
+ ZipFile zipFile = new ZipFile(file);
+ zipFile.setFileNameCharset("GBK");
+
+ // 给要删除的目录加上路径分隔符
+ if (!removeDir.endsWith(File.separator)) removeDir += File.separator;
+
+ // 如果目录不存在, 直接返回
+ FileHeader dirHeader = zipFile.getFileHeader(removeDir);
+ if (null == dirHeader) return;
+
+ // 遍历压缩文件中所有的FileHeader, 将指定删除目录下的子文件名保存起来
+ List headersList = zipFile.getFileHeaders();
+ List removeHeaderNames = new ArrayList();
+ for(int i=0, len = headersList.size(); i