编辑:已解决。我通过将jdbc连接器写入数据库,获取blob并将其转储到文件中来绕过ibatis / ApachePOI。总有一天,我想确切地知道它为什么搞砸了 - 但今天我很高兴有这个支持我。
总结:我正在使用Oracle blob并使用Apache POI重新构建Excel二进制文件以通过SOAP服务层。 .Net客户端正好将这些文件写入.xls文件,但在写入UNIX目录时文件已损坏。
详情: 我有一个存储在oracle表中的Excel blob。这些blob是使用iBatis编写的,并使用此(截断的)结果映射进行拉取。
<resultMap id="report" class="Report">
<result column="content" property ="content" typeHandler="BlobByteArrayTypeHandler"/>
我们的Java服务使用Apache.POI生成excel报告。目前,我们的客户端(.net)向服务查询一个字节数组,该数组被写入Windows机器而没有错误 - 只是将字节转储到文件中。
这些excel文件很好。
我遇到的问题是我们有一个新要求,即我们应该将这些文件写入UNIX文件系统,以便进一步处理。
所有尝试都失败了。以下是一些代码示例:
private void writeReportDumpBytes(Report report) {
File file = new File("report.xls");
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(report.getContent());
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeReportWithEncoding(Report report, String encoding) {
File file = new File("Report.xls");
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, encoding);
Writer out = new BufferedWriter(outputStreamWriter);
String reportBytes = new String(report.getContent());
out.write(reportBytes.toCharArray());
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeReportHssfPoifileSystem(Report report) {
try {
InputStream byteStream = new ByteArrayInputStream(report.getContent());
POIFSFileSystem fs = new POIFSFileSystem(byteStream);
HSSFWorkbook workbook = new HSSFWorkbook(fs);
FileOutputStream fileOut = new FileOutputStream("Report.xls");
workbook.write(fileOut);
fileOut.flush();
fileOut.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
private void writeReportApacheIO(Report report) {
File file = new File("Report.xls");
try {
logReportBytes(report, "Apache IO");
FileUtils.writeByteArrayToFile(file, report.getContent());
} catch (IOException e) {
log.error("Caught IOException", e);
}
}
为了诊断这一点,我尝试从Oracle获取blob并将其保存到文件中。在一个简单的jar可执行文件中,我已经能够从这个文件中读取字节,并在我们的UNIX机器上使用上述方法重写它 - 它们都可以工作。
但是,从我们的代码中,excel文件都已损坏,或者缺少来自Apache.POI的头信息。在文本编辑器中打开损坏/错误的二进制文件显示64字节的重复模式。它不是有效的xls二进制文件。
有些事情正在横行。 blob是一个有效的xls二进制文件,我们只是获取字节(使用上面的iBatis)并将它们传回HSSFWorkbook对象,并尝试使用我已经显示过的方法进行编写。
/**
* Return the byte array based on the workbook.
*
* @return
* @throws IOException
*/
public byte[] getContent() throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
this.workBook.write(bos);
return bos.toByteArray();
}
使用Apache POI时遇到的具体错误是:
java.io.IOException: block[ 0 ] already removed
at org.apache.poi.poifs.storage.BlockListImpl.remove(BlockListImpl.java:97)
at org.apache.poi.poifs.storage.BlockAllocationTableReader.fetchBlocks(BlockAllocationTableReader.java:190)
at org.apache.poi.poifs.storage.BlockListImpl.fetchBlocks(BlockListImpl.java:130)
at org.apache.poi.poifs.property.PropertyTable.<init>(PropertyTable.java:79)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:171)