学习目标
了解压缩流的主要作用
了解JAVA IO支持的三种压缩格式
掌握ZipOutputStream、ZipFile、ZipInputStream三个类的使用
压缩文件大致可以分为三种:ZIP、JAR、GZ
压缩流
在日常的使用中经常会使用到像WinRAR或WinZIP这样的压缩文件,通过这些软件可以把一个很大的文件进行压缩以方便传输。
在JAVA中 为了减少传输时的数据量也提供了专门的压缩流,可以将文件或文件夹压缩成ZIP、JAR、GZIP等文件的格式。
压缩流的实现
ZIP是一种较为常见的压缩形式,在Java中要想实现ZIP的压缩需要导入java.util.zip包,可以使用此包中的ZipFile、ZipOutputStream、ZipInputStream、ZipEntry几个类完成。
JAR及GZIP文件格式的压缩输入、输出流:
在JAVA IO中,不仅可以实现ZIP压缩格式的输入、输出,也可以实现JAR及GZIP文件格式的压缩:
JAR压缩的支持类保存在java.util.jar包中,常用的类有如下几个:
JAR压缩输出流:JarOutputStream
JAR压缩输入流:JarInputStream
JAR文件:JARFile
JAR实体:JAREntry
GZIP是用于UNIX系统的文件压缩,在Linux中经常会使用到*.gz的文件,就是GZIP格式,GZIP压缩的支持类保存在java.util.zip包中,常用的类有如下几个:
GZIP压缩输出流:GZIPOutputStream
GZIP压缩输入流:GZIPInputStream
正常情况下在IO操作中,所有的类库都是在io包中。
ZipEntry:
在每一个压缩文件中都会存在多个子文件,那么这每一个的子文件在JAVA中就使用ZipEntry表示。
ZipEntry类的常用方法:
public ZipEntry(String name) 构造方法 创建对象并指定要创建的ZipEntry名称。
public boolean isDirectory() 普通方法 判断ZipEntry是否是目录。
在实例化ZipEntry的时候,要设置名称,此名称实际上就是压缩文件中的每一个元素中的名称。
ZipOutputStream:
如果要想完成一个文件或文件夹的压缩,要使用ZipOutputStream类完成,ZipOutputStream是OutputStream的子类。
public ZipOutputStream(OutputStream out) 构造方法 创建新的ZIP输出流。
public void putNextEntry(ZipEntry e) throws IOException 普通方法 设置每一个ZipEntry对象。
public void setComment(String comment) 设置ZIP文件的注释
此类的功能就是完成ZIP格式输出的。继承关系如下:
从定义中可以看出,其实就是一个字节的输出流。
在压缩文件中,每一个压缩的内容都可以用一个ZipEntry表示,所以在进行压缩之前必须通过putNextEntry设置一个ZipEntry即可。
- import java.io.File ;
- import java.io.FileInputStream ;
- import java.io.InputStream ;
- import java.util.zip.ZipEntry ;
- import java.util.zip.ZipOutputStream ;
- import java.io.FileOutputStream ;
- public class ZipOutputStreamDemo01{
- public static void main(String args[]) throws Exception{ // 所有异常抛出
- File file = new File("d:" + File.separator + "liuxun.txt") ; // 定义要压缩的文件
- File zipFile = new File("d:" + File.separator + "liuxun.zip") ; // 定义压缩文件名称
- InputStream input = new FileInputStream(file) ; // 定义文件的输入流
- ZipOutputStream zipOut = null ; // 声明压缩流对象
- zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ;
- zipOut.putNextEntry(new ZipEntry(file.getName())) ; // 设置ZipEntry对象
- zipOut.setComment("压缩流测试") ; // 设置注释
- int temp = 0 ;
- while((temp=input.read())!=-1){ // 读取内容
- zipOut.write(temp) ; // 压缩输出
- }
- input.close() ; // 关闭输入流
- zipOut.close() ; // 关闭输出流
- }
- };
压缩一个非嵌套型文件夹
以上是对一个文件进行压缩,但是在日常的开发中,往往需要对一个文件夹进行压缩,例如,现在在某盘存在一个liuxun的文件夹。从使用各种压缩软件的经验来看,如果现在要进行压缩的话,则在压缩之后的文件中应该存在一个liuxun的文件夹。在文件夹中应该存放着各个压缩文件。所以在实现的时候就应该列出文件夹中的全部内容,并把每一个内容设置成ZipEntry的对象,保存到压缩文件之中。
程序代码如下:
- import java.io.File ;
- import java.io.FileInputStream ;
- import java.io.InputStream ;
- import java.util.zip.ZipEntry ;
- import java.util.zip.ZipOutputStream ;
- import java.io.FileOutputStream ;
- public class ZipOutputStreamDemo02{
- public static void main(String args[]) throws Exception{ // 所有异常抛出
- File file = new File("d:" + File.separator + "liuxun") ; // 定义要压缩的文件夹
- File zipFile = new File("d:" + File.separator + "liuxundir.zip") ; // 定义压缩文件名称
- InputStream input = null ; // 定义文件输入流
- ZipOutputStream zipOut = null ; // 声明压缩流对象
- zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ;
- zipOut.setComment("liuxunTEST") ; // 设置注释
- int temp = 0 ;
- if(file.isDirectory()){ // 判断是否是文件夹
- File lists[] = file.listFiles() ; // 列出全部文件
- for(int i=0;i<lists.length;i++){
- input = new FileInputStream(lists[i]) ; // 定义文件的输入流
- zipOut.putNextEntry(new ZipEntry(file.getName()
- +File.separator+lists[i].getName())) ; // 设置ZipEntry对象
- while((temp=input.read())!=-1){ // 读取内容
- zipOut.write(temp) ; // 压缩输出
- }
- input.close() ; // 关闭输入流
- }
- }
- zipOut.close() ; // 关闭输出流
- }
- };
递归实现嵌套文件或文件夹的压缩(转自别人的)
- import java.io.File ;
- import java.io.FileInputStream ;
- import java.io.InputStream ;
- import java.util.zip.ZipEntry ;
- import java.util.zip.ZipOutputStream ;
- import java.io.FileOutputStream ;
- public class ZipOutputStreamDemo02{
- public static void main(String args[]) throws Exception{ // 所有异常抛出
- File file = new File("/Users/liuxun/Downloads/liuxun") ; // 定义要压缩的文件夹
- File zipFile = new File("/Users/liuxun/Downloads/liuxundir.zip") ; // 定义压缩文件名称
- zipMultiFile("/Users/liuxun/Downloads/liuxun", "/Users/liuxun/Downloads/liuxundir.zip", true);
- }
- /*
- * 压缩整个文件夹中的所有文件,生成指定名称的zip压缩包
- * @param filepath 文件所在目录
- * @param zippath 压缩后zip文件名称
- * @param dirFlag zip文件中第一层是否包含一级目录,true包含;false没有
- * 2015年6月9日
- */
- public static void zipMultiFile(String filepath ,String zippath, boolean dirFlag) {
- try {
- File file = new File(filepath);// 要被压缩的文件夹
- File zipFile = new File(zippath);
- ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
- if(file.isDirectory()){
- File[] files = file.listFiles();
- for(File fileSec:files){
- if(dirFlag){
- recursionZip(zipOut, fileSec, file.getName() + File.separator);
- }else{
- recursionZip(zipOut, fileSec, "");
- }
- }
- }
- zipOut.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private static void recursionZip(ZipOutputStream zipOut, File file, String baseDir) throws Exception{
- if(file.isDirectory()){
- File[] files = file.listFiles();
- for(File fileSec:files){
- recursionZip(zipOut, fileSec, baseDir + file.getName() + File.separator);
- }
- }else{
- byte[] buf = new byte[1024];
- InputStream input = new FileInputStream(file);
- zipOut.putNextEntry(new ZipEntry(baseDir + file.getName()));
- int len;
- while((len = input.read(buf)) != -1){
- zipOut.write(buf, 0, len);
- }
- input.close();
- }
- }
- };
ZipFile
是一个专门表示压缩文件的类,在JAVA中,每一个压缩文件都可以使用ZipFile表示,还可以使用ZipFile根据压缩后的文件名称找到每一个压缩文件中的ZipEntry并将其进行解压缩操作。
1、public ZipFile(File file) throws ZipException,IOException 构造方法 根据File类实例化ZipFile对象。
2、public ZipEntry getEntry(String name) 根据名称找到其对应的ZipEntry。
3、public InputStream getInputStream(ZipEntry entry) throws IOException 根据ZipEntry取得InputStream对象。
4、public String getName() 得到压缩文件的路径名称。
ZipFile在实例化的时候必须接收File类的实例,此File类的实例是指向一个压缩的*.zip文件。
首先需要为ZipFile实例化,实例化时需要接收File类的引用。
- import java.io.File ;
- import java.io.FileInputStream ;
- import java.io.InputStream ;
- import java.util.zip.ZipEntry ;
- import java.util.zip.ZipOutputStream ;
- import java.util.zip.ZipFile ;
- import java.io.FileOutputStream ;
- public class ZipFileDemo01{
- public static void main(String args[]) throws Exception{ // 所有异常抛出
- File file = new File("d:" + File.separator + "liuxun.zip") ; // 找到压缩文件
- ZipFile zipFile = new ZipFile(file) ; // 实例化ZipFile对象
- System.out.println("压缩文件的名称:" + zipFile.getName()) ; // 得到压缩文件的名称
- }
- };
- import java.io.File ;
- import java.io.FileInputStream ;
- import java.io.InputStream ;
- import java.io.OutputStream ;
- import java.util.zip.ZipEntry ;
- import java.util.zip.ZipOutputStream ;
- import java.util.zip.ZipFile ;
- import java.io.FileOutputStream ;
- public class ZipFileDemo02{
- public static void main(String args[]) throws Exception{ // 所有异常抛出
- File file = new File("d:" + File.separator + "liuxun.zip") ; // 找到压缩文件
- File outputFile = new File("d:" + File.separator + "liuxun_unzip.txt") ; // 定义解压缩的文件名称
- ZipFile zipFile = new ZipFile(file) ; // 实例化ZipFile对象
- ZipEntry entry = zipFile.getEntry("test.txt") ; // 得到一个压缩实体
- OutputStream out = new FileOutputStream(outputFile) ; // 实例化输出流
- InputStream input = zipFile.getInputStream(entry) ; // 得到一个压缩实体的输入流
- int temp = 0 ;
- while((temp=input.read())!=-1){
- out.write(temp) ;
- }
- input.close() ; // 关闭输入流
- out.close() ; // 关闭输出流
- }
- };
ZipInputStream
此类的定义如下:
java.lang.Object
java.io.InputStream
java.io.FilterInputStream
java.util.zip.InflaterInputStream
java.util.zip.ZipInputStream
可以不用输入实体名称,就可以得到每一个ZipEntry对象
- import java.io.File ;
- import java.io.FileInputStream ;
- import java.io.InputStream ;
- import java.util.zip.ZipEntry ;
- import java.util.zip.ZipInputStream ;
- import java.io.FileInputStream ;
- public class ZipInputStreamDemo01{
- public static void main(String args[]) throws Exception{ // 所有异常抛出
- File zipFile = new File("d:" + File.separator + "test.zip") ; // 定义压缩文件名称
- ZipInputStream input = null ; // 定义压缩输入流
- input = new ZipInputStream(new FileInputStream(zipFile)) ; // 实例化ZIpInputStream
- ZipEntry entry = input.getNextEntry() ; // 得到一个压缩实体
- System.out.println("压缩实体名称:" + entry.getName()) ;
- input.close() ;
- }
- };
ZipFile对象,可以找到每一个ZipEntry的输入流。但是ZipInputStream并不能得到每一个输入流,所以需要使用ZipFile,但是ZipInputStream在取得每一个ZipEntry的时候,不需要每一个ZipEntry的名称。
- import java.io.File ;
- import java.io.OutputStream ;
- import java.io.InputStream ;
- import java.util.zip.ZipEntry ;
- import java.util.zip.ZipFile ;
- import java.util.zip.ZipInputStream ;
- import java.io.FileInputStream ;
- import java.io.FileOutputStream ;
- public class ZipInputStreamDemo02{
- public static void main(String args[]) throws Exception{ // 所有异常抛出
- File file = new File("d:" + File.separator + "lx.zip") ; // 定义压缩文件名称
- File outFile = null ; // 输出文件的时候要有文件夹的操作
- ZipFile zipFile = new ZipFile(file) ; // 实例化ZipFile对象
- ZipInputStream zipInput = null ; // 定义压缩输入流
- OutputStream out = null ; // 定义输出流,用于输出每一个实体内容
- InputStream input = null ; // 定义输入流,读取每一个ZipEntry
- ZipEntry entry = null ; // 每一个压缩实体
- zipInput = new ZipInputStream(new FileInputStream(file)) ; // 实例化ZIpInputStream
- while((entry = zipInput.getNextEntry())!=null){ // 得到一个压缩实体
- System.out.println("解压缩" + entry.getName() + "文件。") ;
- outFile = new File("d:" + File.separator + entry.getName()) ; // 定义输出的文件路径
- if(!outFile.getParentFile().exists()){ // 如果输出文件夹不存在
- outFile.getParentFile().mkdir() ; // 创建文件夹
- }
- if(!outFile.exists()){ // 判断输出文件是否存在
- outFile.createNewFile() ; // 创建文件
- }
- input = zipFile.getInputStream(entry) ; // 得到每一个实体的输入流
- out = new FileOutputStream(outFile) ; // 实例化文件输出流
- int temp = 0 ;
- while((temp=input.read())!=-1){
- out.write(temp) ;
- }
- input.close() ; // 关闭输入流
- out.close() ; // 关闭输出流
- }
- input.close() ;
- }
- };
总结:
1、压缩文件中的每一个压缩实体都使用ZipEntry保存,一个压缩文件中可能包含一个或多个ZipEntry对象。
2、在JAVA中可以进行zip、jar、gz三种格式的压缩支持,操作流程基本上是一致的。
3、ZipOutputStream可以进行压缩的输出,但是输出的位置不一定是文件。
4、ZipFile表示每一个压缩文件,可以得到每一个压缩实体的输入流。
学习目标
了解压缩流的主要作用
了解JAVA IO支持的三种压缩格式
掌握GZIPInputStream、GZIPOutputStream的使用
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
- import java.util.zip.GZIPInputStream;
- import java.util.zip.GZIPOutputStream;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipFile;
- /**
- * @author tanml
- * 将一串数据按照gzip方式压缩和解压缩
- */
- public class GZipUtils {
- // 压缩
- public static byte[] compress(byte[] data) throws IOException {
- if (data == null || data.length == 0) {
- return null;
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- GZIPOutputStream gzip = new GZIPOutputStream(out);
- gzip.write(data);
- gzip.close();
- return out.toByteArray();//out.toString("ISO-8859-1");
- }
- public static byte[] compress(String str) throws IOException {
- if (str == null || str.length() == 0) {
- return null;
- }
- return compress(str.getBytes("utf-8"));
- }
- // 解压缩
- public static byte[] uncompress(byte[] data) throws IOException {
- if (data == null || data.length == 0) {
- return data;
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(data);
- GZIPInputStream gunzip = new GZIPInputStream(in);
- byte[] buffer = new byte[256];
- int n;
- while ((n = gunzip.read(buffer)) >= 0) {
- out.write(buffer, 0, n);
- }
- gunzip.close();
- in.close();
- return out.toByteArray();
- }
- public static String uncompress(String str) throws IOException {
- if (str == null || str.length() == 0) {
- return str;
- }
- byte[] data = uncompress(str.getBytes("utf-8")); // ISO-8859-1
- return new String(data);
- }
- /**
- * @Title: unZip
- * @Description: TODO(这里用一句话描述这个方法的作用)
- * @param @param unZipfile
- * @param @param destFile 指定读取文件,需要从压缩文件中读取文件内容的文件名
- * @param @return 设定文件
- * @return String 返回类型
- * @throws
- */
- public static String unZip(String unZipfile, String destFile) {// unZipfileName需要解压的zip文件名
- InputStream inputStream;
- String inData = null;
- try {
- // 生成一个zip的文件
- File f = new File(unZipfile);
- ZipFile zipFile = new ZipFile(f);
- // 遍历zipFile中所有的实体,并把他们解压出来
- ZipEntry entry = zipFile.getEntry(destFile);
- if (!entry.isDirectory()) {
- // 获取出该压缩实体的输入流
- inputStream = zipFile.getInputStream(entry);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] bys = new byte[4096];
- for (int p = -1; (p = inputStream.read(bys)) != -1;) {
- out.write(bys, 0, p);
- }
- inData = out.toString();
- out.close();
- inputStream.close();
- }
- zipFile.close();
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- return inData;
- }
- public static void main(String[] args){
- String json = "{\"androidSdk\":22,\"androidVer\":\"5.1\",\"cpTime\":1612071603,\"cupABIs\":[\"armeabi-v7a\",\"armeabi\"],\"customId\":\"QT99999\",\"elfFlag\":false,\"id\":\"4a1b644858d83a98\",\"imsi\":\"460015984967892\",\"system\":true,\"systemUser\":true,\"test\":true,\"model\":\"Micromax R610\",\"netType\":0,\"oldVersion\":\"0\",\"pkg\":\"com.adups.fota.sysoper\",\"poll_time\":30,\"time\":1481634113876,\"timeZone\":\"Asia\\/Shanghai\",\"versions\":[{\"type\":\"gatherApks\",\"version\":1},{\"type\":\"kernel\",\"version\":9},{\"type\":\"shell\",\"version\":10},{\"type\":\"silent\",\"version\":4},{\"type\":\"jarUpdate\",\"version\":1},{\"type\":\"serverIps\",\"version\":1}]}";
- json="ksjdflkjsdflskjdflsdfkjsdf";
- try {
- byte[] buf = GZipUtils.compress(json);
- File fin = new File("D:/temp/test4.txt");
- FileChannel fcout = new RandomAccessFile(fin, "rws").getChannel();
- ByteBuffer wBuffer = ByteBuffer.allocateDirect(buf.length);
- fcout.write(wBuffer.wrap(buf), fcout.size());
- if (fcout != null) {
- fcout.close();
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }