2013-12-12 78 views
0

首先,請原諒我的糟糕編碼!
從內存文件創建磁盤上的Zip文件

要求:
1.創建XLS /從數據庫的ResultSet內存XLSX報告(即純文本文件不應該被寫入到磁盤)。
2.在磁盤上創建ZIP從內存中的xlsx文件。

環境:
WinXP SP2上JDK1.6_06,Zip4j1.3.1,poi3.8

我使用Apache的POI和Zip4j和我下面Mr.Shrikant的例子在 「http://www.lingala.net/zip4j/forum/index.php?topic=257.0

公佈

觀察:
1.該程序將27,842字節的xlsx文件寫入磁盤以獲取樣本數據。
2.相同的工作手冊創建ByteArrayOutputStream,大小爲baoStream 49022bytes
3.加密和壓縮後,創建大小爲3984字節的文件。
4.在提取Zip文件,
一)WinZip的,拋出錯誤
B)的Winrar 「意外的文件結尾」,拋出 「CRC錯誤」

請糾正我,無論我錯了,提高,無論我貧窮!

在此先感謝!

package zipconversion; 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.ResultSetMetaData; 
import java.sql.Statement; 
import java.sql.Types; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Date; 
import java.util.List; 

import java.util.Random; 
import net.lingala.zip4j.io.ZipOutputStream; 
import net.lingala.zip4j.model.ZipParameters; 
import net.lingala.zip4j.util.Zip4jConstants; 
import org.apache.poi.ss.usermodel.CellStyle; 
import org.apache.poi.xssf.usermodel.XSSFCell; 
import org.apache.poi.xssf.usermodel.XSSFCellStyle; 
import org.apache.poi.xssf.usermodel.XSSFColor; 
import org.apache.poi.xssf.usermodel.XSSFFont; 
import org.apache.poi.xssf.usermodel.XSSFRow; 
import org.apache.poi.xssf.usermodel.XSSFSheet; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

public class ZipCreationInMemory { 

    ZipOutputStream zos = null; 
    XSSFWorkbook workbook = null; 
    ByteArrayOutputStream baoStream = null; 
    String path = null; 
    String xlsxfileExtn = null; 
    String zipfileExtn = null; 
    String onlyFileName = null; 
    String xlsxFileName = null; 
    String zipFileName = null; 
    String xlsxFilePath = null; 
    String zipFilePath = null; 

    public static int randInt(int min, int max) { 
     Random rand = new Random(); 
     int randomNum = rand.nextInt((max - min) + 1) + min; 
     return randomNum; 
    } 

    public void createXlsxFile() { 
     try { 
      SimpleDateFormat timeFormat = new SimpleDateFormat("hh_mm_ss"); 
      path = "D:\\abcd\\"; 
      xlsxfileExtn = ".xlsx"; 
      zipfileExtn = ".zip"; 
      onlyFileName = "ReportData_".concat(timeFormat.format(new Date())); 
      xlsxFileName = onlyFileName + xlsxfileExtn; 
      zipFileName = onlyFileName + zipfileExtn; 
      xlsxFilePath = path + xlsxFileName; 
      zipFilePath = path + zipFileName; 
      FileOutputStream out = new FileOutputStream(new File(xlsxFilePath)); 
      workbook = new XSSFWorkbook(); 
      XSSFSheet sheet = workbook.createSheet("Report"); 
      XSSFRow rowHead = sheet.createRow((short) 0); 

      XSSFCellStyle headStyle = workbook.createCellStyle(); 
      XSSFFont headerFont = workbook.createFont(); 
      headerFont.setBold(true); 
      headerFont.setColor(new XSSFColor(new java.awt.Color(255, 0, 0))); 
      headStyle.setFont(headerFont); 
      headStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 255, 255))); 
      headStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); 

      XSSFCellStyle oddStyle = workbook.createCellStyle(); 
      oddStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(randInt(125, 255), randInt(125, 255), randInt(125, 255)))); 
      oddStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); 

//JDBC CONFIGURATIONS 
      Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance(); 
      String dbURL = "jdbc:derby://localhost:1527/DATABASE_NAME;create=true;user=USER_ID;password=PASSWORD"; 

      Connection connection = DriverManager.getConnection(dbURL); 
      Statement st = connection.createStatement(); 
      ResultSet resultSet = st.executeQuery("Select * from TABLE_NAME"); 
      ResultSetMetaData metaData = resultSet.getMetaData(); 
      int colCount = metaData.getColumnCount(); 

      SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss"); 



      for (int curColIndx = 0; curColIndx < colCount; curColIndx++) { 
       XSSFCell cell = rowHead.createCell((short) curColIndx); 
       cell.setCellStyle(headStyle); 
       cell.setCellValue(metaData.getColumnName(curColIndx + 1)); 
      } 
      int index = 1; 
      while (resultSet.next()) { 
       XSSFRow row = sheet.createRow((short) index); 

       for (int curColIndx = 0; curColIndx < colCount; curColIndx++) { 
        XSSFCell cell = row.createCell((short) curColIndx); 
        if (index % 2 == 1) { 
         cell.setCellStyle(oddStyle); 
        } 
        else { 
         cell.setCellStyle(evenStyle); 
        } 
        int type = metaData.getColumnType(curColIndx + 1); 
        if (type == Types.TIMESTAMP) { 
         cell.setCellValue(sdf.format(resultSet.getDate(curColIndx + 1))); 
        } else if (type == Types.VARCHAR || type == Types.CHAR) { 
         cell.setCellValue(resultSet.getString(curColIndx + 1)); 
        } else { 
         cell.setCellValue(resultSet.getLong(curColIndx + 1)); 
        } 
       } 

       index++; 
      } 
      baoStream = new ByteArrayOutputStream(); 
      try { 
//This Writes 27,842 bytes xlsx file to disk for sample data. 
       workbook.write(out); 
//same workbook is written to ByteArrayOutputStream() 
       workbook.write(baoStream); 
//But, baoStream size is 49022bytes and After Encryption and Zipping It Creates File of Size 43,084 bytes. 
       System.out.println("baoStream.size() :" + baoStream.size()); 
       try { 
        //byte[] bytesToWrite = getBytesFromFile(); 
        byte[] bytesToWrite = baoStream.toByteArray(); 
        InMemoryOutputStream inMemoryOutputStream = new InMemoryOutputStream(); 

        zos = new ZipOutputStream(inMemoryOutputStream); 

        ZipParameters parameters = new ZipParameters(); 
        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); 
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); 
        parameters.setFileNameInZip(xlsxFileName); 
        parameters.setSourceExternalStream(true); 

        zos.putNextEntry(null, parameters); 
        zos.write(bytesToWrite); 
        zos.closeEntry(); 
        zos.finish(); 
        zos.close(); 

        // Write contents in our InMemoryOutputStream to a zip file to test if this worked 
        writeContentsToZipFile(inMemoryOutputStream); 

       } catch (Exception e) { 
        e.printStackTrace(); 
       } 

       out.close(); 
       resultSet.close(); 
       connection.close(); 
       System.out.println("Excel written successfully.."); 
      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

     } catch (Exception e) { 
      System.out.println("Exception is :" + e.toString()); 
     } 
    } 

    public ZipCreationInMemory() { 
     //testZipCreationInMemory(); 
     createXlsxFile(); 
    } 


package zipconversion; 

import java.io.IOException; 
import java.io.OutputStream; 
import java.util.ArrayList; 
import java.util.List; 

/** 
* Writes the content to memory. 
* 
*/ 
public class InMemoryOutputStream extends OutputStream { 

    // As we cannot know the size of the zip file that is being created, 
    // we cannot maintain a byte array. We will copy all the bytes that 
    // gets passed in the write() method to a List. Once all writing is done, 
    // we can create a byte array from this List and this will be the content 
    // of the zip file 
    private List byteList; 

    // flag to keep track if the outputstream is closed 
    // no further write operations should be performed once this stream is closed 
    private boolean closed; 

    public InMemoryOutputStream() { 
     byteList = new ArrayList(); 
     closed = false; 
    } 

    public void write(int b) throws IOException { 
     if (closed) { 
      throw new IOException("trying to write on a closed output stream"); 
     } 

     byteList.add(Integer.toString(b)); 
    } 

    public void write(byte[] b) throws IOException { 
     if (b == null) { 
      return; 
     } 
     write(b, 0, b.length); 
    } 

    public void write(byte[] b, int off, int len) throws IOException { 
     if (closed) { 
      throw new IOException("trying to write on a closed output stream"); 
     } 

     if (b != null && len > 0) { 
      for (int i = 0; i < len; i++) { 
       byteList.add(Byte.toString(b[i])); 
      } 
     } 
    } 

    public byte[] getZipContent() { 
     if (byteList.size() <= 0) { 
      return null; 
     } 

     byte[] zipContent = new byte[byteList.size()+1]; 

     for (int i = 0; i < byteList.size(); i++) { 
      zipContent[i] = Byte.parseByte((String) byteList.get(i)); 
     } 
      return zipContent; 
    } 

    public void close() throws IOException { 
     closed = true; 
    } 
} 
+3

你爲什麼打這個電話? 'zos.putNextEntry(null,parameters);'你在zip中添加了一個空條目,這些工具正確地告訴你你的損壞條目(**你使其爲空**)。 –

+1

你有太多的事情在單一的方法進行。試着改善這一點。 –

+0

zos.putNextEntry(null,parameters);在壓縮文件中添加文件名。 – AVA

回答

0

的錯誤是可能的方法writeContentsToZipFile(inMemoryOutputStream),但你沒有發佈它的源代碼

我認爲class InMemoryOutputStream不需要實現,它不是有效的,並導致更多的問題。

  • 如果你想保存壓縮內容文件,用FileOutputStream
  • 如果你想保存在內存中的zip內容替換它,與ByteArrayInputStream inMemoryOutputStream = new ByteArrayInputStream(bytesToWrite.length);

注意替換:第一個參數zos.putNextEntry(null, parameters)爲空。 它工作時parameters.setSourceExternalStream(true)。在這種模式下,文件名和其他參數通過ZipParameters提供。

相關問題