2014-11-04 2464 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你可以得到所有的内置特性,和自定义的过于访问!