Java 压缩和解压,附赠文件筛选和拷贝 学习中的一些收获

写在前面:
因本人水平较低,进行代码编写时也是根据CSDN上大佬们的代码,参考编写的,所以,侵删,侵删。。

环境介绍

使用的是JDK1.8,IDEA编辑器

压缩流程及代码

通过获得源文件路径,和要压缩到的目地路径(这里如果不传参数,默认当前目录下),对文件进行判断是文件还是文件夹,是文件就调用压缩方法,进行压缩,文件夹就调用文件夹递归方法,递归到文件时调用压缩方法。
接下来上代码:

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Zipfile {
    public Zipfile() {
    }
    //单文件夹或者单文件
    /**
     * 压缩文件
     * zippath     压缩源文件路径
     * zipFileName 压缩目标文件路径,需要是一个文件名,且必须存在(Fileoutstream调用)
     */
    public String Tozip(String dirpath, String zipFileName) {
        String str = null;
        try {
            File zipFile = new File(zipFileName);
            if (zipFile.exists()) {
                zipFile.delete();
            }
            zipFile.createNewFile();//创建文件
            FileOutputStream fos = new FileOutputStream(zipFile);
            BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);
            ZipOutputStream zos = new ZipOutputStream(bos);//压缩输出流
            File dirFile = new File(dirpath);
            if (dirFile.isDirectory()) {
                str = directoryZip(zos, dirFile, "");
            } else {//压缩单文件
                str = onefilezip(dirFile, zos, zipFile);           
            }
            zos.close();
            bos.close();
            fos.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        //返回压缩后文件路径
        return str;
    }

    /**
     * 压缩文件夹
     * 添加到压缩文件中
     * @param out  源文件流对象
     * @param f    目地文件对象
     * @param base 用于子目录录入
     * @throws Exception
     */
    private String directoryZip(ZipOutputStream out, File f, String base) throws Exception {
        // 如果传入的是目录
        if (f.isDirectory()) {
            File[] fl = f.listFiles();
            // 创建压缩的子目录
            out.putNextEntry(new ZipEntry(base + "/"));
            if (base.length() == 0) {
                base = "";
            } else {
                base = base + "/";
            }
            for (int i = 0; i < fl.length; i++) {
                directoryZip(out, fl[i], base + fl[i].getName());
            }
        } else {
            File file = new File(base);
            onefilezip(f, out, file);
        }
        System.out.println("file compress:" + f.getCanonicalPath());
        //表示与此抽象路径名相同的文件或目录的规范路径名字符串
        return f.getCanonicalPath();
    }

    public String onefilezip(File dirFile, ZipOutputStream zos, File zipFile) {
        byte[] buffer = new byte[1024];
        ZipEntry zipEntry = null;
        int readLength = 0;     //每次读取出来的长度
        InputStream is = null;
        String str = null;

        try {
            BufferedInputStream bin = new BufferedInputStream(new FileInputStream(dirFile));
            DataInputStream dis = new DataInputStream(bin);//增强
            //输出-写出数据
            zipEntry = new ZipEntry(dirFile.getName());  //获得压缩文件条目
            zos.putNextEntry(zipEntry);
            while ((readLength = dis.read(buffer)) != -1) {//每次读取1024(缓冲区大小)
                zos.write(buffer, 0, readLength);
                zos.flush();
            }
            str = zipFile.getCanonicalPath();
            System.out.println("file compress:" + zipFile.getCanonicalPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str;
    }
}

刚开始编写压缩代码的时候并没有使用BufferedInputStream,DataInputStream,只是简单的使用 FileInputStream去进行压缩,于是压缩文件打不开,压缩文件损坏。。。。特别是对图片进行压缩,最是让我头疼,最后找到了这个增强方法,使用后,嗯,NIce!VeryGood!
对于压缩途中数据出错问题,还有几个检查的类,例如 CheckedOutputStream(对输出文件做CRC32校验)感兴趣的,有需要的可以自行搜索。

解压流程及代码

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class Unzip {
    //把zip解压缩到path下
    // 文件对象,解压路径  File file, String path
    public boolean unzip(String filepath, String unpath) {
        File file = new File(filepath);
        try {
            ZipFile zip = new ZipFile(file);
            for (Enumeration<?> entries = zip.entries(); entries.hasMoreElements(); ) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                String name = entry.getName();
                System.out.println("解压:" + name);
                unprocess(entry,unpath,zip,name);
            }
        } catch (IOException e) {
        }
        return true;
    }

    private void unprocess(ZipEntry entry,String unpath,ZipFile zip,String name){
        try {
            if (entry.isDirectory()) {
                File dir = new File(unpath + File.separator + name);
                dir.mkdir();
            } else {
                File unfile = new File(unpath + File.separator + name);
                if (!unfile.getParentFile().exists())
                    unfile.getParentFile().mkdirs();
                unfile.createNewFile();
                InputStream in = zip.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(unfile);
                int len;
                byte[] buf = new byte[1024 * 20];
                while ((len = in.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                    fos.flush();
                }
                fos.close();
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //循环输出文件名
//   private void printzipFile(File dfile) {
//        if (dfile.exists()) {
//            if (dfile.isFile()) {
//                System.out.println(dfile.toString());
//                return;
//            }
//            if (dfile.isDirectory()) {
//                System.out.println(dfile.toString());
//                File[] files = dfile.listFiles();
//                for (int i = 0; i < files.length; i++) {
//                    printzipFile(files[i]);
//                }
//            }
//        }
//        return;
//    }
}

对文件路径处理

我在进行压缩和解压的时候,对路径的处理单独列出了一个类,因为要处理多种情况:
首先源文件夹路径是必须有的,无论是压缩还是解压
1.目的路径无,默认其压缩到当前文件夹下
2.目的路径非当前文件夹下,这种就直接传递过去就可以
压缩:
要求更改压缩文件后缀名,这就要对上面两个问题再判断
解压:
解压时同样考虑1,2两种情况,但是解压出来是文件夹,路径名就不同了,就要和压缩分开考虑,于是又定义两个个方法。。。

import java.io.File;

public class Getpath {
	//suffix 后缀名
    public String getzpath(String filepath, String targetpath, String suffix) {
        String path = null;
        int f = filepath.lastIndexOf("\\");
        int t = targetpath.length();
        if (f == t || targetpath == null) {
            path = getCzippath(filepath, suffix);
        } else {
            path = getzippath(filepath, targetpath, suffix);
        }
        return path;
    }

    //当前文件夹下
    private String getCzippath(String Cfilepath, String suffix) {
        String zipfilename = null;
        if (suffix == null || suffix.length() <= 0) {
            suffix = "zip";
        }
        int indexof = Cfilepath.lastIndexOf(".");
        if (indexof == -1 && indexof <= 0) {
            zipfilename = Cfilepath + "." + suffix;
        } else {
            zipfilename = Cfilepath.substring(0, indexof + 1) + suffix;
        }
        //返回压缩文件夹路径
        return zipfilename;
    }

    //zipfilepath:要压缩到的文件夹路径  filepath:源文件路径 suffix 后缀名
    private String getzippath(String filepath, String zipfilepath, String suffix) {
        String zipfilename = null;
        if (suffix == null || suffix.length() <= 0) {
            suffix = "zip";
        }
        File file = new File(filepath);
        int indexof = file.getName().lastIndexOf(".");
        if (indexof == -1 && indexof <= 0) {
            zipfilename = zipfilepath + "\\" + file.getName() + "." + suffix;
        } else {
            //目标文件夹路径+文件名(去后缀,保留.)+zip
            zipfilename = zipfilepath + "\\" + file.getName().substring(0, indexof + 1) + suffix;
        }
        return zipfilename;
    }

    public String getunpath(String filepath, String targetpath) {
        String path = null;
        int f = filepath.lastIndexOf("\\");
        int t = targetpath.length();
        if (f == t || targetpath == null) {
            path = getCunzippath(filepath);
        } else {
            path = getunzippath(filepath, targetpath);
        }
        return path;
    }

    private String getCunzippath(String Cfilepath) {
        int indexof = Cfilepath.lastIndexOf(".");
        if (indexof == -1 && indexof <= 0) {
        } else {
            Cfilepath = Cfilepath.substring(0, indexof);
        }
        //返回压缩文件夹路径
        return Cfilepath;
    }

    private String getunzippath(String filepath, String targetpath) {
        File file = new File(filepath);
        int indexof = file.getName().lastIndexOf(".");
        if (indexof == -1 && indexof <= 0) {
            targetpath = targetpath + "\\" + file.getName();
        } else {
            //目标文件夹路径+文件名(去后缀,保留.)+zip
            targetpath = targetpath + "\\" + file.getName().substring(0, indexof);
        }
        return targetpath;
    }
}

附赠 文件过滤,和拷贝

我在进行压缩解压缩的时候,想处理同一个文件夹下的多文件,怎么办–>把它们过滤出来,组成数组,循环处理!又不想对原数据进行处理(要是我写的代码有问题,把原数据整没了怎么办),于是我就i想到复制一份!

过滤代码

(考虑到文件后缀的大小写和格式不同的问题,比如png,jpg;于是写了一个能过滤两个后缀名的方法)

import java.io.File;
import java.io.FilenameFilter;

public class Filterfile implements FilenameFilter {
   private String suffix;//后缀名

    public void setsuffix(String suffix) {
        this.suffix = suffix;
    }

    public boolean accept(File dir, String name) {
        return name.endsWith(suffix);
    }
    //多文件名后缀筛选File dirFile, String s1, String s2
    public String[] filterfile(File dirFile, String s1, String s2) {
        this.setsuffix(s1);
        String[] results1 = dirFile.list(this);
        this.setsuffix(s2);
        String[] results2 = dirFile.list(this);
        //合并数组
        String[] results = new String[results1.length + results2.length];
        System.arraycopy(results1, 0, results, 0, results1.length);
        System.arraycopy(results2, 0, results, results1.length, results2.length);
        return results;

    }
}
//使用例
 File dirfile = new File("筛选文件所在的文件夹路径");
 Filterfile filter = new Filterfile();
 String result = dirFile.list(filter);//单文件后缀名
 String[] results = filter .filterfile(dirFile, s1, s2);//s1,s2:两个后缀

方法返回的是文件名数组(不是绝对路径)
关于FilenameFilter接口,推荐一篇文章:FilenameFilter接口详解

拷贝部分

import interfaceclass.Icopy;
import java.io.*;
import java.util.ArrayList;
public class Copy implements Icopy {
    public Copy() {
    }
    /**
     * 配合文件筛选方法使用
     * @param path 源文件路径
     * @param results   筛选文件名数组
     * @param realPath  处理后,目标路径
     */
    public void TocNewFile(String path, String[] results, String realPath) {
        //为文件添加路径
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 0; i < results.length; i++) {
            list.add(path + "\\" + results[i]);
        }
        System.out.println("筛选出的文件的路径:");
        for (String name : list) {
            System.out.println(name);
        }
        //判断解压目标文件夹是否存在
        File realfile = new File(realPath);
        if (!realfile.exists()) {//如果文件夹不存在
            realfile.mkdir();//创建文件夹
        }
        //循环解压
        for (int i = 0; i < list.size(); i++) {
            cNewFile(path, realPath, results[i]);
        }
    }
    private File cNewFile(String path, String realpath, String newFileName) {
        File file = new File(path);    // path原文件路径,被复制的文件
        File dir = new File(realpath);  // realPath复制的目标路径
        if (!dir.exists()) {    // 判断路径是否存在
            dir.mkdirs();
        }
        File newFile = new File(realpath, newFileName); // 创建新文件对象
        try {
            newFile.createNewFile();        // 创建新文件
            fileChannelCopy(file, newFile); // 复制模板到新文件
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newFile;
    }

    // 以文件通道的方式读取、写入文件
    private void fileChannelCopy(File s, File t) {
        try {
            InputStream in = null;
            OutputStream out = null;
            try {
                in = new BufferedInputStream(new FileInputStream(s), 1024);
                out = new BufferedOutputStream(new FileOutputStream(t), 1024);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
            } finally {
                if (null != in) {
                    in.close();
                }
                if (null != out) {
                    out.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

十分感谢CSDN上的博主们,分享的经验与代码

因为开始敲代码的时候也没想过写一篇文章,觉得压缩和解压缩是比较简单的事情(于是就没记下那些文章地址,一周后,难寻…),等到实际去做才知道360压缩之类的压缩工具背后隐藏的一角。突然就有了—路漫漫其修远兮,吾将上下而求索。 的感悟!
最后再次强调,部分代码确实参考(嗯,文化人,参考!)其他文章,侵删。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值