JAVA導出Excel、TXT、批量導出ZIP

目標

實現JAVA導出Excel、TXT、批量導出ZIP文件。

知識點

1.字節流與字符流

區別:

讀寫單位:顧名思義,字節流以字節(byte)爲讀寫單位,而字符流以字符爲讀寫單位,根據碼錶映射字符,一次可能讀入多個字符。
處理對象:字節流可以處理所有類型的數據(包括圖片等),而字符流只能處理字符類型的純文本數據。
字節流:一次寫入或讀出8位二進制。
字符流:一次寫入或讀出至少8位二進制。不同的字符所佔的字節是不同的。

ASCII碼:
一個英文字母(不分大小寫)佔一個字節的空間,一箇中文漢字佔兩個字節的空間。一個二進制數字序列,在計算機中作爲一個數字單元,一般爲8位二進制數,換算爲十進制。最小值0,最大值255。如一個ASCII碼就是一個字節。

UTF-8編碼:
一個英文字符等於一個字節,一箇中文(含繁體)等於三個字節。

Unicode編碼:
一個英文等於兩個字節,一箇中文(含繁體)等於兩個字節。

2.簡述頁面導出文件的邏輯(直接導出TXT,一般讀寫流(stream)的時候,數據是先被讀到了內存中,再把數據寫到文件中)

  • 設置reponse響應
  • 獲取輸出流response.getOutputStream();
  • 將文件內容以字節流形式寫入
  • 清空緩存區數據,把緩衝區的數據強行輸出 flush()
  • 關閉輸出流
/* 導出txt文件
	 * @author	
	 * @param	response
	 * @param	text 要導出的字符串
	 * @return
	 */
	public void exportTxt(HttpServletResponse response,String text){
		response.setCharacterEncoding("utf-8");
        //設置響應的內容類型
        response.setContentType("text/plain");
        //設置文件的名稱和格式
        response.addHeader("Content-Disposition","attachment;filename="
        					+ new String(("文件中文名稱").getBytes("gb2312"),"iso8859-1")//設置名稱格式,沒有這個中文名稱無法顯示
                        + ".txt");
        BufferedOutputStream buff = null;
        ServletOutputStream outStr = null;
        try {
            outStr = response.getOutputStream();
            buff = new BufferedOutputStream(outStr);
            buff.write(text.getBytes("UTF-8"));
            buff.flush();
            buff.close();
        } catch (Exception e) {
            //LOGGER.error("導出文件文件出錯:{}",e);
        } finally {try {
                buff.close();
                outStr.close();
            } catch (Exception e) {
                //LOGGER.error("關閉流對象出錯 e:{}",e);
            }
        }
	}

java頁面導出TXT
SSM框架下導出TXT,參考【SSM框架, 導出TXT

3. 一些類

  • BufferedInputStream: 輸入緩衝流:先從磁盤中將要讀取的內容放入到內存中,再一次性從內存中取出來,避免了讀一段取一段;(未使用) 構造需基於outputStream
public void readFileWithBufferedStream(String srcPath, int size) {
        InputStream inputStream = null;
        BufferedInputStream bufferedInputStream = null;
        StringBuffer sb = new StringBuffer();
        try {
            inputStream = new FileInputStream(srcPath);
            bufferedInputStream = new BufferedInputStream(inputStream);
            byte[] byteArr = new byte[size];
            int len = 0;
            while ((len = bufferedInputStream.read(byteArr)) != -1) {
                sb.append(new String(byteArr), 0, len);
            }
            System.out.println(sb);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
  • BufferedOutputStream: 輸出緩衝流:先將要輸出的內容放入到內存中,再一次性全都輸出。構造需基於outputStream
    public void writeFileWithBufferedStream(String content, String destPath) {
        OutputStream outputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {
            // 下面的語句中,如果destPath中的目錄不存在,不會自動創建目錄,因此,建議使用下面的代碼
            // outputStream = new FileOutputStream(destPath);
       // 前提是輸出的路徑是"/"而不是"\\"
            File tmp = new File(destPath.substring(0, destPath.lastIndexOf("/")));
            if(!tmp.exists()){
                tmp.mkdirs();
            }
            outputStream = new FileOutputStream(destPath);
            bufferedOutputStream = new BufferedOutputStream(outputStream);

            byte[] byteArr = content.getBytes();
            bufferedOutputStream.write(byteArr);
            bufferedOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
  • XSSFWorkbook類 excel2007文檔對象;構造基於inputStream
//後面用到
public static void exportExcelFromContent(HttpServletResponse response, String data, String savefileName)
            throws Exception{

        BASE64Decoder base64Decoder = new BASE64Decoder();
        byte[] b =base64Decoder.decodeBuffer(data); //data爲經過base64加密的字符,所以解碼爲字節流
        InputStream inputStream = new ByteArrayInputStream(b);

        Workbook wb = null;
        String headStr = "attachment; filename=" + new String((savefileName).getBytes("gb2312"),"iso8859-1");

        //製表平臺只支持xlsx
        headStr +='.xlsx';
        wb= new XSSFWorkbook(inputStream);
        //輸出流
        OutputStream out = null;
        try{
            response.setContentType("APPLICATION/OCTET-STREAM");
            response.setHeader("Content-Disposition", headStr);
            out = response.getOutputStream();
            wb.write(out);
        }
        catch (IOException e){
            logger.error("導出Excel文件出錯!", e);
        } finally{
            if(out != null){
                out.close();
            }
        }
    }
  • ZipOutputStream
    ZipInputStream “壓縮文件輸入流”,用於讀取磁盤上的壓縮文件
    ZipOutputStream “壓縮文件輸出流”,用於將程序中的壓縮流寫出到磁盤上。
    通常需要使用ZipFile ZipInputStream/ZipOutputStream ZipEntry級File完成解壓縮操作
//壓縮 文件
    public static void doCompress(ZipOutputStream zos, File file, String baseDir) throws Exception {
        if (file.isDirectory()) {
            // 遞歸循環,只壓縮其中所有文件
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                doCompress(zos, files[i], baseDir);
            }
        } else {
            // 進行文件壓縮的操作
            byte[] buff = new byte[DEFAULT_BUFF_SIZE];
            InputStream in = new FileInputStream(file);
            zos.putNextEntry(new ZipEntry(baseDir + File.separator + file.getName()));
            int len;
            while ((len = in.read(buff,0 ,DEFAULT_BUFF_SIZE)) != -1) {
                zos.write(buff, 0, len);
            }
            in.close();
        }
    }

單個及批量導出EXcel文件

@RequestMapping(value ="/exportReport.json")
 public void exportFile(HttpServletResponse response, String action , String filenameList )throws Exception{
        try {
            JSONArray jsonArray = JSONArray.fromObject(filenameList);
            List<Map<String, String>> resultMap = JSONArray.toList(jsonArray, new HashMap<String, String>(), new JsonConfig());
            if(resultMap.size() == 1){
                //單個導出
                String reportName = resultMap.get(0).get("reportName");
                String coop_branch_no = String.valueOf(resultMap.get(0).get("coop_branch_no"));
                String reportId = StringUtils.equals("0",coop_branch_no)? String.valueOf(resultMap.get(0).get("report_id")) : String.valueOf(resultMap.get(0).get("report_id"))+"[" + coop_branch_no + "]" ;
                String branchNo = String.valueOf(resultMap.get(0).get("branch_no"));
                //報送導出頁面 period_date=0L
                String reportContent = bizReportService.getReportContent(reportId, branchNo, coop_branch_no,0L); //獲取EXcel文件內容,reportContent爲base64編碼後的字符
                FileUtils.exportExcelFromContent(response, reportContent, StringUtils.equals("0",coop_branch_no)? reportName:reportName+"[" + coop_branch_no + "]");
            }else if(resultMap.size() > 1){
                //批量導出
                String reportName,coop_branch_no,branchNo,reportId,filePath = "";
                response.reset();
                //用於輸出新生成文件名 keys: filePath  fileName
                List<Map<String, String>> filePaths = new ArrayList<>();
                for(Map<String,String> file : resultMap){
                    Map<String,String> zipFileOutput = new HashMap<>();
                    if(file != null){
                        //組合成完整的文件路徑
                        reportName = String.valueOf(file.get("reportName"));
 						String newFileName = StringUtils.equals("0",coop_branch_no)? reportName + ".xlsx" :reportName+"[" + coop_branch_no + "]" + ".xlsx";
                        zipFileOutput.put("reportId",reportId);
                        zipFileOutput.put("branchNo",branchNo);
                        zipFileOutput.put("coop_branch_no",coop_branch_no);
                        zipFileOutput.put("fileName",newFileName);
                        filePaths.add(zipFileOutput);
                    }
                }

                //創建壓縮文件需要的空的zip包
                Date date = new Date();
                SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
                String zipName = dateFormat.format(date) + ".zip";
                String zipFilePath = filePath+zipName;

                //壓縮文件
                File zip = new File(zipFilePath);
                if (!zip.exists()){
                    zip.createNewFile();
                }

                //創建zip文件輸出流
                ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
                this.zipFileFromContent(filePaths, zos);
                zos.close();
                //設置編碼字符
                response.setContentType("text/html; charset=UTF-8");
                //設置內容類型爲下載類型
                response.setContentType("application/octet-stream");
                //設置下載的壓縮文件名稱
                response.setHeader("Content-disposition", "attachment;filename="+zipName);
                //創建頁面返回方式爲輸出流,會自動彈出下載框
                OutputStream out = response.getOutputStream();

                //將打包後的文件使用緩衝流輸出;這種方式與直接 outputStream輸出文件內容的字節流,不太一樣;這裏先讀後寫
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipFilePath));
                byte[] buff = new byte[bis.available()];
                bis.read(buff);
                bis.close();
                //輸出數據文件
                out.write(buff);
                //釋放緩存
                out.flush();
                //關閉輸出流
                out.close();
                new File(zipFilePath).delete();
            }
        } catch (Exception e) {
            logger.error("導出excel文件出錯:"+e.getMessage());
        }
    }
    
    //私有方法
   private String zipFileFromContent(List<Map<String, String>> filePaths, ZipOutputStream zos) throws IOException {

        //循環讀取集合,獲取每一個報表信息以獲取報表內容
        for(Map<String,String> filePath : filePaths){
            String reportContent = bizReportService.getReportContent(filePath.get("reportId"), filePath.get("branchNo"),
                    filePath.get("coop_branch_no"),0L);
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] b =base64Decoder.decodeBuffer(reportContent);
            InputStream in = new ByteArrayInputStream(b);

            //創建輸入流讀取文件
            BufferedInputStream bis = new BufferedInputStream(in) ;
            //將文件寫入zip內,即將文件進行打包
            zos.putNextEntry(new ZipEntry(filePath.get("fileName")));
            //寫入文件的方法,同上
            int size = 0;
            //設置讀取數據緩存大小
            byte[] buffer = new byte[1024];
            while ((size = bis.read(buffer)) > 0) {
                zos.write(buffer, 0, size);
            }
            //關閉輸入輸出流
            zos.closeEntry();
            bis.close();
        }
        return null;
    }

批量導出TXT文件

@RequestMapping(value ="/exportTXT.json")
    public void exportTXT(String txtnameList, HttpServletResponse resp)throws Exception {
        // 清空輸出流
        resp.reset();
        try{
            JSONArray jsonArray = JSONArray.fromObject(txtnameList);
            List<Map<String, String>> resultMap = JSONArray.toList(jsonArray, new HashMap<String, String>(), new JsonConfig());
            if(resultMap.size() == 1){
                String reportId = resultMap.get(0).get("report_id");
                String branchNo = resultMap.get(0).get("branch_no");
                String reportName = resultMap.get(0).get("reportName");
                String coopBranchNo = resultMap.get(0).get("coop_branch_no");
                String periodDate = "0";
                String reportData = uraReportExportService.exportTXTFile(reportId, branchNo, coopBranchNo, periodDate);
                if ("fail".equals(reportData)) {
                    logger.error("獲取TXT內容失敗");
                } else {
                    resp.setCharacterEncoding("UTF-8");
                    // 設定輸出文件頭
                    resp.setHeader("Content-disposition", "attachment; filename=" + new String((reportName).getBytes("gb2312"),"iso8859-1") + ".TXT");
                    // 定義輸出類型
                    resp.setContentType("text/plain");
                    //輸出流
                    BufferedOutputStream buff = null;
                    OutputStream out = resp.getOutputStream();
                    buff = new BufferedOutputStream(out);
                    buff.write(reportData.getBytes("utf-8"));
                    buff.flush();
                    buff.close();
                    logger.info("TXT文件導出成功");
                }
            } else if(resultMap.size() > 1){
                //批量導出TXT
                String reportName,coopBranchNo,branchNo,reportId,filePath = "";
                resp.reset();
                List<Map<String, String>> filePaths = new ArrayList<>();
                for(Map<String,String> file : resultMap){
                    Map<String,String> zipFileOutput = new HashMap<>();
                    if(file != null){
                        //組合成完整的文件路徑
                        reportName = String.valueOf(file.get("reportName"));               
                        String newFileName = StringUtils.equals("0",coopBranchNo)? reportName + ".TXT" :reportName+"[" + coopBranchNo + "]" + ".TXT";
                        zipFileOutput.put("reportId",reportId);
                        zipFileOutput.put("branchNo",branchNo);
                        zipFileOutput.put("coop_branch_no",coopBranchNo);
                        zipFileOutput.put("fileName",newFileName);
                        filePaths.add(zipFileOutput);
                    }
                }

                //創建壓縮文件需要的空的zip包
                String zipBasePath= filePath ;
                Date date = new Date();
                SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
                String zipName = dateFormat.format(date) + ".zip";
                String zipFilePath = filePath+zipName;

                //壓縮文件
                File zip = new File(zipFilePath);
                if (!zip.exists()){
                    zip.createNewFile();
                }

                //創建zip文件輸出流
                ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
                this.zipFileFromTXTContent(filePaths, zos);
                zos.close();
                //設置編碼字符
                resp.setContentType("text/html; charset=UTF-8");
                //設置內容類型爲下載類型
                resp.setContentType("application/octet-stream");
                //設置下載的壓縮文件名稱
                resp.setHeader("Content-disposition", "attachment;filename="+zipName);
                //創建頁面返回方式爲輸出流,會自動彈出下載框
                OutputStream out = resp.getOutputStream();

                //將打包後的文件使用緩衝流輸出
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipFilePath));
                byte[] buff = new byte[bis.available()];
                bis.read(buff);
                bis.close();
                //輸出數據文件
                out.write(buff);
                //釋放緩存
                out.flush();
                //關閉輸出流
                out.close();
                new File(zipFilePath).delete();
            }
        } catch (Exception e){
            logger.error("TXT導出失敗",e.toString());
        }
      }

以上

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章