首先,请原谅我糟糕的编码!
要求:
1.从数据库ResultSet在内存中创建xls / xlsx报告(即,不应将纯文本文件写入磁盘)。
2.在磁盘上创建ZIP从内存中的xlsx文件。
环境:
WinXP SP2,JDK1.6_06,Zip4j1.3.1,poi3.8
我正在使用Apache的POI和Zip4j,并且正在关注在“http://www.lingala.net/zip4j/forum/index.php?topic=257.0”发表的Mr.Shrikant的例子
观察:
1.此程序将27,842字节的xlsx文件写入磁盘以获取样本数据
2.同一个工作簿创建ByteArrayOutputStream,baoStream的大小为49022bytes
3.加密和压缩后,它创建大小为43,084字节的文件
4.在提取Zip文件时,
a)WinZip,抛出错误“UnExpected End of File”
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;
}
}
答案 0 :(得分:0)
方法writeContentsToZipFile(inMemoryOutputStream)
中可能存在错误,但您没有发布它的源代码......
我认为class InMemoryOutputStream
的实施不是必需的,它不起作用并导致更多问题。
FileOutputStream
ByteArrayInputStream inMemoryOutputStream = new ByteArrayInputStream(bytesToWrite.length);
注意:zos.putNextEntry(null, parameters)
的第一个参数为null。
它适用于parameters.setSourceExternalStream(true)
。在此模式下,文件名和其他参数通过ZipParameters提供。