Java之缩略图工具Thumbnailator

This commit is contained in:
sxyx2008
2014-07-30 13:46:48 +08:00
parent f506135a85
commit fef502223c
15 changed files with 1458 additions and 15 deletions
+26 -3
View File
@@ -26,7 +26,7 @@
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/xxx.jar</systemPath>
</dependency>
-->
<!-- 读写二维码 -->
<dependency>
@@ -44,8 +44,8 @@
<artifactId>qrgen</artifactId>
<version>1.3</version>
</dependency>
<!-- Java缩略图生成类库 -->
<dependency>
<groupId>net.coobird</groupId>
@@ -53,7 +53,30 @@
<version>0.4.7</version>
</dependency>
<!-- 时间类库 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.4</version>
</dependency>
<!-- zip4j zip压缩类库 -->
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
</project>
@@ -3,7 +3,7 @@ package org.javase.tutorials;
/**
* 二分法查找
* @author welcome
* @author 冯靖
*
*/
public class BinarySearch {
@@ -2,7 +2,7 @@ package org.javase.tutorials;
/**
* 交换两个数的值,不借助于第三个数
* @author welcome
* @author 冯靖
*
*/
public class SwapVar {
@@ -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"));
}
}
@@ -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());
@@ -4,6 +4,8 @@ import java.util.Arrays;
/**
* 排序算法接口
* @author 冯靖
*
*/
public interface Sort {
@@ -6,7 +6,9 @@ import org.javase.tutorials.sort.Sort.SortUtil;
import org.javase.tutorials.sort.Sort.Sorts;
/**
* 冒择入希快归堆:常用排序算法
* 常用排序算法
* @author 冯靖
*
*/
public class SortTest {
@@ -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"));
}
}
@@ -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压缩文件到指定目录
* <p>
* 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
*
* @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压缩文件到指定目录
* <p>
* 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
*
* @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<FileHeader> headerList = zFile.getFileHeaders();
List<File> extractedFileList = new ArrayList<File>();
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);
}
/**
* 使用给定密码压缩指定文件或文件夹到指定位置.
* <p>
* dest可传最终压缩文件存放的绝对路径,也可以传存放目录,也可以传null或者"".<br />
* 如果传null或者""则将压缩文件存放在当前目录,即跟源文件同目录,压缩文件名取源文件名,以.zip为后缀;<br />
* 如果以路径分隔符(File.separator)结尾,则视为目录,压缩文件名取源文件名,以.zip为后缀,否则视为文件名.
*
* @param src
* 要压缩的文件或文件夹路径
* @param dest
* 压缩文件存放路径
* @param isCreateDir
* 是否在压缩文件里创建目录,仅在压缩文件为目录时有效.<br />
* 如果为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<File> temp = new ArrayList<File>();
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<String> removeHeaderNames = new ArrayList<String>();
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();
}
}
}
@@ -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<File> filesToAdd = new ArrayList<File>();
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<File> filesToAdd = new ArrayList<File>();
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<File> filesToAdd = new ArrayList<File>();
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<File> filesToAdd = new ArrayList<File>();
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();
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

@@ -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/
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.
@@ -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压缩文件到指定目录
* <p>
* 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
* @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压缩文件到指定目录
* <p>
* 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
* @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<FileHeader> headerList = zFile.getFileHeaders();
List<File> extractedFileList = new ArrayList<File>();
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);
}
/**
* 使用给定密码压缩指定文件或文件夹到指定位置.
* <p>
* dest可传最终压缩文件存放的绝对路径,也可以传存放目录,也可以传null或者"".<br />
* 如果传null或者""则将压缩文件存放在当前目录,即跟源文件同目录,压缩文件名取源文件名,以.zip为后缀;<br />
* 如果以路径分隔符(File.separator)结尾,则视为目录,压缩文件名取源文件名,以.zip为后缀,否则视为文件名.
* @param src 要压缩的文件或文件夹路径
* @param dest 压缩文件存放路径
* @param isCreateDir 是否在压缩文件里创建目录,仅在压缩文件为目录时有效.<br />
* 如果为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<File> temp = new ArrayList<File>();
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<String> removeHeaderNames = new ArrayList<String>();
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);
}
public static void main(String[] args) {
zip("d:\\test\\cc", "d:\\test\\cc.zip", "11");
try {
File[] files = unzip("d:\\test\\汉字.zip", "aa");
for (int i = 0; i < files.length; i++) {
System.out.println(files[i]);
}
} catch (ZipException e) {
e.printStackTrace();
}
}
}