zoukankan      html  css  js  c++  java
  • java原生文件打包

    一、背景

    前端时间,自己做的项目需要打包功能,不想再引外部的jar包

    便用java.util.zip做了下该功能

    二、适用场景

    生成多个word、excel、xml等文件,并要求打包下载的情形

    例:项目信息的多选导出word

    三、实现

    实现分为三个部分,分别是

    1、将字符串保存为文件,都是最基本的IO操作

        /**
         * @Description 将字符串保存为文件
         * @author liuy-8
         * @date 2015年5月20日 下午1:48:18 
         * @param filePath
         * @param content
         */
        public static void saveFile(String filePath, String content){
            File file = new File(filePath);
            FileWriter fw = null;
            //这里没有使用BufferWrite,是因为数据是一次性写入
            //BufferWrite的优势在于调用write方法时,使用缓冲区
            //而FileWriter每次调用write方法,都调用StreamEncoder的write方法
            try {
                fw = new FileWriter(file);//缓冲区1024字符
                fw.write(content);
                fw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally{
                //关闭FileWriter
                try {
                    if(null != fw)
                        fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                
            }
        }

    2、扫描指定文件夹下所有的文件,准备压缩包的写入工作

    这一部分依然是基本的IO操作,要注意安全关闭输入输出流,打开与关闭的顺序

        /**
         * @Description 获取文件夹中所有文件路径
         * @author liuy-8
         * @date 2015年5月27日 下午5:25:24 
         * @param folderPath 文件夹路径
         * @return 文件夹中所有文件路径
         */
        public static List<String> getFilesPath(String folderPath){
            List<String> filesPath = new ArrayList<String>();
            File folder = new File(folderPath);
            File[] fileList = folder.listFiles();
            for(File file : fileList){
                if(file.isDirectory()){
                    //是文件夹,递归遍历
                    filesPath.addAll(getFilesPath(file.getPath()));
                }else{
                    //是文件,加入文件列表
                    filesPath.add(file.getPath());
                }
            }
            return filesPath;
        }
    
        /**
         * @Description 压缩文件夹
         * @author liuy-8
         * @date 2015年5月26日 下午1:42:00 
         * @param folderPath    文件夹路径
         * @param zipFilePath    压缩文件路径
         */
        public static void folder2Zip(String folderPath, String zipFilePath){
            //获取当前系统文件分隔符
            String fileSeparator = System.getProperty("file.separator");
            //若传入路径最后没有文件分隔符,加上
            if(folderPath.lastIndexOf(fileSeparator) != (folderPath.length() - 1)){
                folderPath = folderPath + fileSeparator;
            }
            //获取文件夹下所有文件路径
            List<String> filesPath = getFilesPath(folderPath);
            //文件输出流
            FileOutputStream fos = null;
            //缓冲输出流
            BufferedOutputStream bos = null;
            //zip输出流
            ZipOutputStream zos = null;
            try {
                fos = new FileOutputStream(zipFilePath);
                bos = new BufferedOutputStream(fos);
                zos = new ZipOutputStream(bos);
                for(String filePath : filesPath){
                    //将文件写入zip输出流
                    writeFile2Zip(folderPath, filePath, zos);
                }
                zos.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally{
                //关闭zip输出流
                try {
                    if(null != zos){
                        zos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //关闭缓冲输出流
                try {
                    if(null != bos){
                        bos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //关闭文件输出流
                try {
                    if(null != fos){
                        fos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    3、将文件依次写入zip输出流

    在第二步已经用ZipOutputStream创建了压缩文件的输出流,这一步里,每个文件都要对应一个ZipEntry对象

    要将这个对象加入到压缩文件的输出流中后再写入数据,并且写完数据必须在输出流中关闭该ZipEntry对象

    这里有2个容易出错的地方:

    一是ZipEntry对象需要一个路径,这个路径是相对于压缩文件夹的相对路径,用来保证子文件夹文件的顺利压入

    二是往zip输出流中写入的字节的时候,要判断循环读取字节时文件输入流中读取了多少字节长度,读多少写多少,不然在文件尾部会出现错误数据

        /**
         * @Description 将文件写入zip输出流
         * @author liuy-8
         * @date 2015年5月27日 下午5:23:42 
         * @param folderPath    待压缩文件夹路径
         * @param filePath        待写入文件
         * @param zos            zip输出流
         */
        private static void writeFile2Zip(String folderPath, String filePath, ZipOutputStream zos){
            //缓冲区
            byte[] bs = new byte[1024];
            //获取文件的相对路径
            String entryName = filePath.substring(filePath.indexOf(folderPath) + folderPath.length());
            //创建zip实体
            ZipEntry entry = new ZipEntry(entryName);
            //输入流
            FileInputStream fis = null;
            //缓冲输入流
            BufferedInputStream bis = null;
            try {
                //将zip实体加入zip输出流
                zos.putNextEntry(entry);
                fis = new FileInputStream(filePath);
                bis = new BufferedInputStream(fis);
                //写入zip输出流
                int len = 0;
                while((len = bis.read(bs, 0, 1024)) > 0){
                    zos.write(bs, 0, len);
                }
                zos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally{
                //关闭entity
                try {
                    zos.closeEntry();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //关闭BufferedInputStream
                try {
                    if(null != bis){
                        bis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //关闭FileInputStream
                try {
                    if(null != fis){
                        bis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    此类已封装为GlodonFileUtil,有需要找我要即可

  • 相关阅读:
    HTTP缓存——协商缓存(缓存验证)
    谷粒商城学习——P119-121映射
    powershell download, 兼容低版本 powershell
    InstallShield 2020 R3 破解补丁 支持 VS2019
    解决react使用antd table组件固定表头后,表头和表体列不对齐以及配置fixed固定左右侧后行高度不对齐
    numFormat 用于千分位的操作
    Jquery+NProgress实现网页进度条显示
    js变量前的+是什么意思
    有没有人遇到过用charles做js文件map时,文件若比较大,会被截掉一些(即映射到的文件不完整)的问题?
    如何写代码
  • 原文地址:https://www.cnblogs.com/xjyh/p/4549520.html
Copyright © 2011-2022 走看看