http://blog.csdn.net/silentbalanceyh/article/details/5252285
(這一個章節將講到Java裡面比較重要的一個章節,這裡說一句抱歉,因為最近換工作的原因,一直沒有時間繼續書寫教程,不過接下來我會一直堅持寫下去的哈,希望大家能夠支援。這個章節主要涉及到常用的檔案讀寫,包括進階的檔案IO內容——java.nio,因為這些內容在如今的一些項目裡面也屬於相當常見的一部分,如果有什麼遺漏或者筆誤的話,希望讀者來Email告知:silentbalanceyh@126.com,謝謝。這一部分篇幅可能比前邊章節長很多,也是為了保證能夠將Java裡面IO和檔案操作部分內能寫的都寫入,如果有遺漏希望讀者來Email,概念上有混淆的地方請告知,裡面有些內容參考了一些原文資料進行了翻譯以及思考註解。)
本章目錄: 1.IO類相關內容 2.檔案和目錄 3.檔案進階操作 【Jar文檔的讀寫(.jar)】 JAR檔案介紹: JAR檔案格式是以流行的ZIP檔案格式為基礎,用於將許多檔案聚集壓縮到一個檔案裡面,與ZIP檔案不同的是,JAR檔案不僅用於壓縮和發布,而且還用於部署和封裝庫、組件和外掛程式程式,並可被像編譯器和JVM這樣的工具直接使用。在JAR檔案中包含特殊的檔案,如manifests和部署描述符,用來只是工具如何處理特定的JAR檔案。 JAR檔案的作用如下: 用於發布和使用類庫 作為應用程式和擴充的構建單元 作為組件、applet或者外掛程式程式的部署單位 用於打包與組件相關聯的輔助資源 JAR檔案格式提供了許多優勢和功能,其中很多是傳統的壓縮格式如ZIP或者TAR所沒有提供的,包括: 安全性:可以對JAR檔案內容加上數字化簽名,這樣,能夠識別簽名的工具就可以有選擇地為您授予軟體安全特權,這是其他檔案做不到的,它還可以檢測代碼是否被篡改過 減少下載時間:如果一個Applet捆綁到一個JAR檔案中,那麼瀏覽器就可以在一個HTTP事務中下載這個Applet的類檔案和相關資源,而不是對每一個檔案開啟一個新串連 壓縮:JAR格式允許您壓縮檔以提高儲存效率 傳輸平台擴充:Java擴充架構(Java Extensions Framework)提供向Java核心平台添加功能的方法,這些擴充是用JAR檔案打包的(Java 3D和JavaMail就是擴充的例子) 包密封:儲存在JAR檔案中的包可以選擇進行密封,以增強版本一致性和安全性,密封一個包意味著包中的所有類都必須在同一個JAR檔案中找到 包版本控制:一個JAR檔案可以包含有關它所包含的檔案的資料,如廠商和版本資訊 可移植性:處理JAR檔案的機制就是Java核心平台API的標準部分 META-INF目錄: 大多數JAR檔案包含一個META-INF目錄,它用於儲存包和擴充的配置資料,如安全性和版本資訊,Java 2平台識別並解釋META-INF目錄中的下述檔案和目錄,以便配置應用程式、擴充應用和類裝載器: MANIFEST.MF:這個manifest檔案定義了與擴充和包相關的資料來源 INDEX.LIST:這個檔案由jar工具的新選項-i產生,它包含在應用程式或者擴充中定義的包的位置資訊,它是JarIndex實現的一部分,並且由類裝載器裝載過程。 XXX.SF:這個是JAR檔案的簽名檔案。預留位置XXX表示了簽名者 XXX.DSA:與簽名檔案相關聯的簽名程式塊檔案,它儲存了用於簽名JAR檔案的公用簽名 Pack200類: Pack200類的全名為:java.util.jar.Pack200,這個類是JDK 1.5過後才有的類,該類主要作用是針對JAR檔案進行高效壓縮,該類的實現是根據Java類特有的結構——合并常量池、去掉誤用資訊、儲存內聯資料結構、使用變數長度編碼、選擇最佳化的代碼類型進行二次壓縮來實現高效壓縮。但是該類是針對Java類進行壓縮的,所以對普通檔案的壓縮和普通壓縮軟體沒有什麼兩樣,但是對於Jar檔案卻能輕易達到10-40%的壓縮率,這在Java應用部署中很有用,尤其針對Java行動裝置 App程式的壓縮和解壓是尤其不錯的做法。其使用主要用於class檔案比較多的情況,當jar中包含的非Java類的資源檔比較多的時候,如JPEG或者GIF,使用gzip格式是最好的選擇,但是如果Jar包中絕大部分都是class內容的話,使用pack200絕對是首選,因為pack200會針對class的java類進行最佳化設計,Pack200的壓縮和解壓縮的速度是很快的,而且壓縮率也是驚人的,試試就知道了。Java命令列也提供了相關的命令工具:pack200 先提供簡單的程式碼片段,再樣本其操作: 壓縮: Pack200.Packer packer = Pack200.newPacker(); OutputStream output = new BufferedOutputStream(new FileOutputStream(outfileName)); packer.pack(new JarFile(jarFile),output); output.close(); 解壓: Pack200.Unpacker unpacker = Pack200.newUnpacker(); OutputStream output = new JarOutputStream(new FileOutputStream(jarFile)); unpacker.unpack(pack200File,output); output.close(); ——[$]Pack200類例子—— package org.susan.java.io;
import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.jar.JarFile; import java.util.jar.Pack200;
public class Pack200Tester { public static void main(String args[]) throws Exception{ JarFile file = new JarFile("D:/work/study.jar"); Pack200.Packer packer = Pack200.newPacker(); OutputStream out = new FileOutputStream("D:/work/study.pack"); packer.pack(file, out); out.close(); File inputFile = new File("D:/work/study.jar"); File outputFile = new File("D:/work/study.pack"); System.out.println("Before Pack Size: " + inputFile.length()); System.out.println("After Pack Size: " + outputFile.length()); } } 這段程式運行後我這裡有這樣的輸出: Before Pack Size: 293695 After Pack Size: 130423 【需要說明的就是:如果JAR本身是一個可執行檔JAR,當被Pack200壓縮過後,如果要執行的話必須解壓才能執行,否則這個JAR檔案會直接拋出錯誤告訴你不能執行,也就是說Pack200針對Jar檔案不是單純的壓縮,是進行了高效率的最佳化,主要目的是為了使得這個Jar在壓縮過後體積減小,但是裡面的類照樣可以引用的,也就是如果是一個java庫的話使用這樣的方式未嘗是一個提供網路jar的比較不錯的方式。】 ——[$]Jar檔案清單—— package org.susan.java.io;
import java.io.IOException; import java.sql.Date; import java.util.Enumeration; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile;
public class JarListReader { public static void main(String args[]) throws IOException { JarFile file = new JarFile("D:/work/study.jar"); Enumeration<JarEntry> e = file.entries(); while (e.hasMoreElements()) { JarEntry entry = e.nextElement(); System.out.println(entry.getName()); long uncompressedSize = entry.getSize(); long compressedSize = entry.getCompressedSize(); long crc = entry.getCrc(); int method = entry.getMethod(); String comment = entry.getComment(); System.out.println(new Date(entry.getTime())); System.out.println("From " + uncompressedSize + " bytes to " + compressedSize); if (method == ZipEntry.STORED) { System.out.println("ZipEntry.STORED"); } else if (method == ZipEntry.DEFLATED) { System.out.println(ZipEntry.DEFLATED); } System.out.println("Its CRC is " + crc); System.out.println(comment); System.out.println(entry.isDirectory());
Attributes a = entry.getAttributes(); if (a != null) { Object[] nameValuePairs = a.entrySet().toArray(); for (int j = 0; j < nameValuePairs.length; j++) { System.out.println(nameValuePairs[j]); } } System.out.println(); } } } 上邊這個類會讀取Jar檔案的清單,這裡輸出我不一一列舉主要是這個檔案裡面太多內容,僅僅列舉其中一部分: META-INF/MANIFEST.MF 2009-12-19 From 74 bytes to 75 8 Its CRC is 3423671674 null false
org/susan/java/basic/BreakContinueMain.class 2009-12-18 From 924 bytes to 538 8 Its CRC is 1903539533 null false 但是這樣並沒有解壓,只是一個讀取過程,這一點希望讀者謹記,如果要解壓,直接使用ZIP解壓的方式也可以操作。 ——[$]從一個URL地址擷取Jar檔案—— package org.susan.java.io;
import java.net.JarURLConnection; import java.net.URL; import java.util.jar.JarFile;
public class JarMainEntry { public static void main(String args[]) throws Exception{ //線上地址“ jar:http://hostname/study.jar!/” URL url = new URL("jar:file:/D://work//study.jar!/"); JarURLConnection con = (JarURLConnection)url.openConnection(); System.out.println(con.getEntryName()); &