編輯:已解決。我通過將jdbc連接器寫入數據庫,獲取blob,並將其轉儲到文件來繞過ibatis/ApachePOI。有一天,我想知道它爲什麼會搞砸 - 但今天我很高興有這個背後。簡介:我正在使用Oracle blob,並使用Apache POI來重組Excel二進制文件以通過SOAP服務層。 .Net客戶端正在將這些文件寫入.xls文件,但在寫入UNIX目錄時已損壞文件。Oracle Blob到XLS工作表
細節: 我有存儲在oracle表中的Excel blob。這些blob是使用iBatis編寫的,並使用這個(截斷的)結果地圖來拉取。
<resultMap id="report" class="Report">
<result column="content" property ="content" typeHandler="BlobByteArrayTypeHandler"/>
excel報告是由我們的Java服務使用Apache.POI生成的。目前,我們的客戶端(.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)
Excel文件是二進制數據。您似乎正在使用作家和編碼,這應該只用於純文本。使用它們與二進制數據打破了事情!如果你把所有的作者都打掉,並且只使用字節/數據流,會發生什麼? – Gagravarr
我的第一個示例僅使用FileOutputStream進行編寫,與工作的.Net代碼非常相似,但不適用於Unix。 – hoosierChessGeek