2015-04-27 70 views
2

編輯:已解決。我通過將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) 
+0

Excel文件是二進制數據。您似乎正在使用作家和編碼,這應該只用於純文本。使用它們與二進制數據打破了事情!如果你把所有的作者都打掉,並且只使用字節/數據流,會發生什麼? – Gagravarr

+0

我的第一個示例僅使用FileOutputStream進行編寫,與工作的.Net代碼非常相似,但不適用於Unix。 – hoosierChessGeek

回答

0

我直接寫了一個JDBC調用DB忽略了ibatis和Apache POI的所有廢話。使用各種磁盤寫入方法工作得很好。