Microsoft 實現的所有 .NET 語言編譯器都是符合 CLS 的,其中包括 Microsoft Visual J# .NET — 一種供希望在 Microsoft .NET Framework 上生成應用程序和服務的 Java 語言開發人員使用的開發工具。(Visual J# .NET 是由 Microsoft 獨立開發的。它沒有經過 Sun Microsystems, Inc. 的認可和批准)這就是為什麼可以在用 J# 編寫的 Windows 窗體和 ASP.NET 應用程序中使用 .Net Framework 類的原因。
SharpZip 應用程序在解壓縮文件時所做的第一件事情,是提示用戶指定應當在其中創建文件的目錄。您可能已經注意到,應用程序顯示了“Browse for Folder”對話框。我傾向於使用 System.Windows.Forms.Design.FolderNameEditor.FolderBrowser 類,但是文檔聲稱該類型支持 .Net Framework 基礎結構,並且不適合直接使用,因此我通過導入 Microsoft Shell Controls and Automation 類型庫,借助於 COM Interop 來使用 Shell32 對象。
從 Zip 文件中提取原始文件(解壓縮)的操作非常簡單:只需調用 ZipFile 對象上的 getInputStream,並傳遞您要為其獲得壓縮文件的條目即可。GetInputStream 方法將產生一個 InputStream,以便您從中讀取存檔條目的內容。
ExtractZipFile Helper 函數為您完成該工作。通過使用單獨的條目將目錄存儲在 Zip 文件中,但每個條目中的文件名也包含目錄信息,因此 ExtractZipFile 忽略了目錄條目,並且從文件名中提取必要的路徑信息。
CreateEmptyZipFile Helper 函數創建一個 Zip 文件並且立即關閉它。結果得到一個不含任何條目的空 Zip 文件。追加或刪除項就沒有那麼簡單了,因為 Java.util.zip 包不提供對 Zip 文件的隨機訪問。對於刪除文件,應當將想要保留的條目復制到新的 Zip 文件。對於添加文件,應當將所有條目復制到新的 Zip 文件,然後追加新條目。復制條目涉及到按照我已經描述的方式從源文件中解壓縮條目,然後將其重新壓縮到目標文件。
private int GetWin32IntConstant(string name) { System.Reflection.Assembly asm = System.Reflection.Assembly.GetAssembly(typeof(com.ms.win32.wina)); Type t = asm.GetType("com.ms.win32.win" + char.ToLower(name[0]), true); System.Reflection.FieldInfo info = t.GetFIEld(name); return int.Parse(info.GetValue(null).ToString()); }
使用該技術檢索 Windows API 常量速度會很慢,因此您在使用該方法時應當小心。另外一個問題是,由於常量在編譯時得不到解析,因此每當您拼錯它們時,都會得到運行時錯誤。在任何情況下,在 .Net 程序集中聲明大多數 Windows API 都可以節省大量工作。例如,SharpZip 示例程序顯示了與每個文件的擴展名相關聯的系統圖標。為此,代碼調用 com.ms.win32.Shell32 接口中定義的 SHGetFileInfo API 以獲得圖標的句柄(參見圖 6)。
盡管 com.ms.win32 命名空間非常巨大,但您應當知道它並未包含每個 Windows API 函數和數據結構。例如,com.ms.win32.Shell32 接口的一個顯著疏忽是 SHBrowseForFolder API,它允許我們顯示“Browse for Folder”對話框,而無需使用 Microsoft Shell Controls and Automation COM 庫。
還請注意,處理回調有點復雜,這是由於 Java 語言不支持委托。對於每個回調類型,都提供了定義函數原型的抽象類。您必須從該類派生以實現處理回調的代碼,然後向 API 調用傳遞該類的一個實例(參見圖 7)。另外一個與 Java 語言有關的較小困難是,按引用傳遞的參數被聲明為數組,但是這只影響調用這些函數的代碼,而不影響基礎功能。
最後,某些 API 調用的轉換非常低劣。一個示例是 waveOutOpen(定義在 Winmm 類中)。DwCallback 參數在 C++ 中用於傳遞事件句柄、窗口句柄、線程 ID 或回調函數,具體取決於 fdwOpen 參數的值。由於 J/Direct 包裝將 dwCallback 參數聲明為 Int32,並且沒有將回調(委托)typecast 到 Int32 的方式,所以必須使用其他通知機制,例如,事件句柄、窗口句柄或線程 ID。