一、前言
在開發的過程中,我們有時候會遇到提供數據下載的功能,當數據量較大的時候,可能需要分開幾個文件,然后再在后台打包成ZIP壓縮文件,傳送到前台。之前博客中有提及過如何用Java實現添加到壓縮文件中,當時只討論了如何單個文件添加壓縮文件,這篇文章將討論多文件壓縮的問題。
二、多文件壓縮
@Test public void test() throws Exception{ // 被壓縮文件 File file = new File("C:\\Users\\Administrator\\Desktop\\文件a.pdf"); File file2 = new File("C:\\Users\\Administrator\\Desktop\\文件b.pdf"); // 輸出文件outputStream File outFile = new File("C:\\Users\\Administrator\\Desktop\\壓縮文件.zip"); FileOutputStream outputStream = new FileOutputStream(outFile); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); // 讀取file文件 FileInputStream inputStream = new FileInputStream(file); byte[] bytes = new byte[inputStream.available()]; inputStream.read(bytes); ZipEntry zipEntry = new ZipEntry(file.getName()); zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(bytes); zipOutputStream.flush(); // 讀取file2文件 inputStream = new FileInputStream(file2); bytes = new byte[inputStream.available()]; inputStream.read(bytes); zipEntry = new ZipEntry(file2.getName()); zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(bytes); zipOutputStream.flush(); // 關閉各種流 zipOutputStream.closeEntry(); inputStream.close(); zipOutputStream.close(); outputStream.close(); }
上述這段代碼,可以實現兩個文件添加到ZIP壓縮文件中。這種面相過程的寫法,在某種程度上符合人的思考邏輯與順序。但這種寫法代碼的耦合性高,代碼復用性差。不是像上述代碼那樣寫死,而是需要到本地文件中去取,又或者從數據庫中拿,還是用POI讀取Excel的方式獲取文件路徑,都不太好處理。人為操作的依賴性強。
三、基於面相對象多文件添加ZIP文件
/** * 文件讀取緩沖區大小 */ private static final int CACHE_SIZE = 1024; @Test public void test2() throws Exception{ // 獲取文件列表 List<File> fileList = this.getFileList(); // 壓縮到ZIP文件中 this.toZIP(fileList); } /** * 獲取文件列表 * @return */ private List<File> getFileList(){ List<File> fileList = new ArrayList<>(); File file = new File("C:\\Users\\Administrator\\Desktop\\文件a.pdf"); File file2 = new File("C:\\Users\\Administrator\\Desktop\\文件b.pdf"); fileList.add(file); fileList.add(file2); return fileList; } /** * 壓縮到ZIP文件中 * @param fileList * @throws Exception */ private void toZIP(List<File> fileList) throws Exception{ // 定義讀取問價及讀取數組 FileInputStream inputStream = null; byte[] bytes = null; // 輸出文件outputStream File outFile = new File("C:\\Users\\Administrator\\Desktop\\壓縮文件.zip"); FileOutputStream outputStream = new FileOutputStream(outFile); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); // 循環寫入ZIP文件 for(File file : fileList){ // 定義實體 ZipEntry zipEntry = new ZipEntry(file.getName()); zipOutputStream.putNextEntry(zipEntry); // 將文件讀到數組中 inputStream = new FileInputStream(file); // 整體讀到內存(文件過大會內存溢出) //bytes = new byte[inputStream.available()]; //inputStream.read(bytes); //zipOutputStream.write(bytes); // 分批讀寫 bytes = new byte[CACHE_SIZE]; int len = 0; while((len = inputStream.read(bytes)) != -1){ zipOutputStream.write(bytes); } zipOutputStream.flush(); } // 關閉各種流 zipOutputStream.closeEntry(); inputStream.close(); zipOutputStream.close(); outputStream.close(); }
該斷代碼中,重新划分獲取文件的模塊,同時增加的循環邏輯,提高代碼的復用。在之前的文章中和上面的代碼中,都需全部數據獲取到數組中,為何這里需要分批讀取呢?當文件大的時候,這樣可以方式內存溢出的問題。而且通常開發者的電腦配置(內存)會高於服務器的內存配置,在開發者的電腦沒問題,不代表生產環境沒有問題,還是推薦使用分批讀取。
Reference:
ryelqy, Java實現添加壓縮文件, https://www.cnblogs.com/ryelqy/p/10104167.html