程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 讓POI架起Java與Office之間的橋梁二

讓POI架起Java與Office之間的橋梁二

編輯:關於JAVA

五、通過eventusermodel讀取文件

  

  通過eventusermodel讀取文件要比使用usermodel復雜得多,但效率也要高不少,因為它要求應用程序一邊讀取數據,一邊處理數據。

  

  eventusermodel實際上模擬了DOM環境下SAX處理XML文檔的辦法,應用程序首先要注冊期望處理的數據,eventusermodel將在遇到匹配的數據結構時回調應用程序注冊的方法。使用eventusermodel最大的困難在於你必須熟悉Excel工作簿的內部結構。

  

  在HSSF中,低層次的二進制結構稱為記錄(Record)。記錄有不同的類型,每一種類型由org.apache.poi.hssf.record包中的一個Java類描述。例如,BOFRecord記錄表示Workbook或Sheet區域的開始,RowRecord表示有一個行存在並保存其樣式信息。

  

  所有具有CellValueRecordInterface接口的記錄表示Excel的單元格,包括NumericRecord、LabelSSTRecord和FormulaRecord(還有其他一些,其中部分已被棄置不用,部分用於優化處理,但一般而言,HSSF可以轉換它們)。

  

  下面是一個注冊事件處理句柄的例子:

  

  private EventRecordFactory factory = new EventRecordFactory();

  factory.registerListener(new ERFListener() {

  public boolean processRecord(Record rec) {

  (got BOF Record);

  return true;

  }

  }, new short[] {BOFRecord.sid});

  factory.processRecords(someInputStream);

  

  六、HSSF電子表格結構

  

  如前所述,HSSF建立在POIFS的基礎上。具體地說,Excel 97+文件是OLE 2復合文檔( OLE 2 Compound Document),底層的OLE 2復合文檔保存了一個總是命名為Workbook(Excel 95除外,HSSF不支持Excel 95)的流。

  

  然而,宏和圖片並不保存在Workbook流,它們有自己獨立的流,有時甚至會放到OLE 2 CDF文件之內的另一個目錄。理想情況下,宏也應該被保留,不過目前POI項目中還沒有合適的API來處理宏。

  

  每一個流之內是一組記錄,一個記錄其實就是一個字節數組,可分為記錄頭、記錄體兩部分。記錄頭指明了記錄的類型(也即ID)以及後繼數據的長度,記錄體被分割成多個字段(FIEld),字段包含數值數據(包括對其他記錄的引用)、字符數據或標記。

  

  Excel工作簿的頂級結構:

  

  Bla.xls {

  OLE2CDF headers

  "Workbook" stream {

  Workbook {

  Static String Table Record..

  Sheet names… and pointers

  }

  Sheet {

  ROW

  ROW

  …

  NUMBER RECORD (cell)

  LABELSST Record (cell)

  …

  }

  Sheet

  }

  }

  … images, Macros, etc.

  Document Summary

  Summary

  

  七、通過HPSF讀取文檔屬性

  

  在Microsoft Word、Excel、PowerPoint等軟件中,用戶可以通過“文件”→“屬性”菜單給文檔添加附加信息,包括文檔的標題、主題、摘要、類別、關鍵詞等,同時應用軟件本身還會加入最後訪問的用戶、最後訪問和修改/打印的日期時間等信息。

  

  文檔的屬性和正文是分開保存的。如前所述,OLE 2 CDF文件內部就象是一個容器,裡面包含許多類似目錄和文件的結構,而POIFS就是用來訪問其中的文件的工具。這些文件也稱為流,文檔的屬性就保存在POIFS文件系統中專用的流裡面。

  

  以一個Word文檔為例:雖然在資源管理器中你只看到一個叫做MyFile.doc的文檔,其實在這個文檔的內部,又包含了一個WordDocument、一個SummaryInformation和一個DocumentSummaryInformation文檔;通常還會有其他的文檔,這裡暫且不管。

  

  你能夠猜出這些文檔(流)分別包含什麼內容嗎?不錯,WordDocument包含了你在Word裡面編輯的文本,文檔的屬性保存在SummaryInformation和DocumentSummaryInformation流裡面。也許將所有屬性保存在單個文檔裡面看起來太簡單了,所以Microsoft決心要使用兩個流,為了使事情更復雜一點,這兩個流的名字前面還加上了八進制的\005字符??這是一個不可打印的字符,因此前面就把它省略了。

  

  Microsoft定義的標准屬性有一個好處,它們並不在乎主文檔到底是什麼類型??不管是Word文檔、Excel工作簿還是PowerPoint幻燈。只要你知道如何讀取Excel文檔的屬性,就知道了如何讀取其他文檔的屬性。

  

  讀取文檔屬性其實並不復雜,因為Java程序可以利用POI項目的HPSF包。HPSF是 Horrible Property Set Format的縮寫,譯成中文就是“討厭的屬性集格式”。HPSF包是POI項目實現的讀取屬性工具,目前還不支持屬性寫入。

  

  對於讀取Microsoft定義的標准屬性,通過HPSF提供的API可以很方便地辦到;但如果要讀取任意屬性集就要用到更一般化的API,可以想象它要比讀取標准屬性的API復雜不少。本文只介紹讀取標准屬性的簡單API,因為對大多數應用程序來說這已經完全足夠了。

  

  下面就是一個讀取OLE 2 CDF文檔的標題(title)屬性的Java程序:

  

  import Java.io.*;

  import org.apache.poi.hpsf.*;

  import org.apache.poi.poifs.eventfilesystem.*;

  

  /**

  * 讀取OLE 2文檔標題的示例程序,

  * 在命令行參數中指定文檔的文件名字。

  */

  

  public class ReadTitle

  {

  public static void main(String[] args) throws IOException

  {

  final String filename = args[0];

  POIFSReader r     = new POIFSReader();

  r.registerListener(new MyPOIFSReaderListener(),

  "\005SummaryInformation");

  r.read(new FileInputStream(filename));

  }

  

  static class MyPOIFSReaderListener

  implements POIFSReaderListener

  {

  public void processPOIFSReaderEvent(POIFSReaderEvent event)

  {

  SummaryInformation si = null;

  try

  {

  si = (SummaryInformation)

  PropertySetFactory.create(event.getStream());

  }

  catch (Exception ex)

  {

  throw new RuntimeException

  ("屬性集流\"" + event.getPath() +

  event.getName() + "\": " + ex);

  }

  

  final String title = si.getTitle();

  

  if (title != null)

  System.out.println("標題: \"" + title + "\"");

  else

  System.out.println("該文檔沒有標題.");

  }

  }

  }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved