2014-11-04 2460 views
4

我需要解除保護的xlsx文件.e.gl Book1.xlsx 下面的代碼首次運行正常,讀取Book1.xlsx,解密並再次將其寫入相同的文件名。使用POIFSFileSystem讀取xlsx文件

public static void unprotectXLSXSheet(String fileName, String password) { 
     try{ 

      POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(fileName)); 
      EncryptionInfo info = new EncryptionInfo(fs); 
      Decryptor d = Decryptor.getInstance(info); 
      d.verifyPassword(password); 
      InputStream is = d.getDataStream(fs); 
      System.out.println(is.available()); 
      XSSFWorkbook wb = new XSSFWorkbook(OPCPackage.open(is)); 
      FileOutputStream fileOut; 
      fileOut = new FileOutputStream(fileName); 
      wb.write(fileOut); 
      fileOut.flush(); 
      fileOut.close(); 
      }catch(FileNotFoundException ex){ 
       ex.printStackTrace(); 
      }catch(IOException ex){ 
       ex.printStackTrace(); 

但是當同樣的代碼試圖訪問新創建的未受保護的Book1.xlsx(或任何其它未受保護的xlsx檔案)失敗,並顯示

Exception in thread "main" org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF) 
    at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:131) 
    at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:104) 
    at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:138) 
    at com.wolseley.Excel.TestMainDummy.unprotectXLSXSheet(TestMainDummy.java:113) 
    at com.wolseley.Excel.TestMainDummy.main(TestMainDummy.java:52) 

我需要幫助閱讀xlsx檔案也解開它使用密碼,如上所述。

回答

5

基本上下面的代碼行不用於辦公2007+ XML文檔:

POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(fileName)); 

所以你首先需要通過調用該檢查頭的輸入流中是否它支持:

POIFSFileSystem.hasPOIFSHeader(is) 

只有解密,如果上述返回true。 hasPOIFSHeader方法需要一個支持標記/重置的輸入流,因此請檢查並將其包裝在PushbackInputStream中,如果不是。

全部放在一起就變成了這樣的事情:

public static void unprotectXLSXSheet(String fileName, String password) throws Exception { 
    InputStream is = null; 
    FileOutputStream fileOut = null; 

    try { 
     is = new FileInputStream(fileName); 
     if (!is.markSupported()) { 
      is = new PushbackInputStream(is, 8); 
     } 

     if (POIFSFileSystem.hasPOIFSHeader(is)) { 
      POIFSFileSystem fs = new POIFSFileSystem(is); 
      EncryptionInfo info = new EncryptionInfo(fs); 
      Decryptor d = Decryptor.getInstance(info); 
      d.verifyPassword(password); 
      is = d.getDataStream(fs); 
     } 

     System.out.println(is.available()); 
     XSSFWorkbook wb = new XSSFWorkbook(OPCPackage.open(is)); 
     fileOut = new FileOutputStream(fileName); 
     wb.write(fileOut); 
     fileOut.flush(); 
    } finally { 
     if (is != null) { 
      is.close(); 
     } 
     if (fileOut != null) { 
      fileOut.close(); 
     } 
    } 
} 
+0

感謝您的見解..,這確實的伎倆。 – JavaTweets 2014-11-04 09:20:31

0

下面的老堆棧溢出答案可能會幫助你從這裏。

Reading property sets from Office 2007+ documents with java poi

類你會想是POIXMLProperties,一樣的東西:

OPCPackage pkg = OPCPackage.open(new File("file.xlsx")); 
POIXMLProperties props = new POIXMLProperties(pkg); 
System.out.println("The title is " + props.getCorePart().getTitle()); 

從POIXMLProperties你可以得到所有的內置特性,和自定義的過於訪問!