在變數、陣列和物件中儲存的資料是暫時存在的,程式結束後它們就會遺失。為了能夠永久保存已建立的數據,需要將其保存在磁碟檔案中,這樣就可以在其他程式中使用它們。 Java的I/O技術可以將資料保存到文字檔案、二進位檔案甚至是ZIP壓縮檔案中,已達到永久性保存資料的要求。掌握I/O處理技術能夠提升對資料的處理能力。
流是一組有序的資料序列,根據操作的類型,可分為輸入流和輸出流兩種。 I/O(Input/Output,輸入/輸出)流提供了一條通道程序,可以使用這條通道把來源中的位元組序列送到目的地。雖然I/O流通常與磁碟檔案存取有關,但是程式的來源和目的地也可以是鍵盤、滑鼠、記憶體或顯示器視窗等。
Java由資料流處理輸入/輸出模式,程式從指向來源的輸入流讀取來源中的數據,來源可以是檔案、網路、壓縮套件或其他資料來源。
輸出流的指向是資料要到達的目的地,程式透過寫入資料流寫入資料把訊息到目的地。
Java語言定義了許多類別專門負責各種方式的輸入/輸出,這類類別都被放在java.io套件中。其中,所有輸入流類別都是抽象類別InputStream(位元組輸入流)或抽象類別Reader(字元輸入流)的子類別;而所有輸出流都是抽象類別OutputStream(位元組輸出流)或抽象類別Writer(字元輸出流)的子類別。
InputStream類別是位元組輸入流的抽象類,是所有位元組輸入流的父類。 InputStream類別的具體層次結構如下所示。
該類別中所有方法遇到錯誤時都會引發IOException異常。下面是對該類別中的一些方法的簡要說明。
read()方法:從輸入流讀取資料的下一個位元組。傳回0-255範圍內的int位元組值。如果因為已經到達流末尾而沒有可用的字節,則傳回值為-1。
read(byte[] b):從輸入流中讀入一定長度的位元組,並以整數的形式傳回位元組數。
mark(int readlimit)方法:在輸入流的目前位置放置一個標記,readlimit參數告知此輸入流在標記位置失效之前允許讀取的位元組數。
reset()方法:將輸入指標傳回目前所做的標記處。
skip(long n)方法:跳過輸入流上的n個位元組並傳回實際跳過的位元組數。
markSupported()方法:如果目前流支援mark()/reset()操作就回傳true。
close方法:關閉此輸入流並釋放與該流關聯的所有系統資源。
Java中的字元是Unicode編碼,是雙位元組的。 InputStream是用來處理位元組的,而且不適合處理字元文字。 Java為字元文字的輸入特別提供了一套單獨的類別Reader,但Reader類別並不是InputStream類別的替換者,只是處理字串時簡化了程式設計。 Reader類別是字元輸入流的抽象類別,所有字元輸入流的實作都是它的子類別。
Reader類別中的方法與InputStream類別中的方法類似,讀者在需要時可查看JDK文檔。
OutputStream類別是位元組輸出流的抽象類,此抽象類別是表示輸出位元組流的所有類別的超類別。
OutputStream類別中的所有方法均傳回void,在遇到錯誤時會引發IoException異常。以下對OutputStream類別中的方法作簡單的介紹。
write(int b)方法:將指定的位元組寫入此輸出流。
write(byte[] b)方法:將b個位元組從指定的byte陣列寫入此輸出流。
write(byte[] b,int off, int len)方法:將指定byte數組中從偏移量off開始的len個位元組寫入此輸出流。
flush()方法:徹底完成輸出並清空快取區。
close()方法:關閉輸出流。
File類別是java.io套件中唯一代表磁碟檔案本身的物件。 File類別定義了一些與平台無關的方法來操作文件,可以透過呼叫File類別中的方法,實現創建、刪除、重新命名文件等操作。 File類別的物件主要用來取得檔案本身的一些訊息,如檔案所在的目錄、檔案的長度、檔案讀寫權限等。資料流可以將資料寫入到檔案中,檔案也是資料流最常用的資料媒體。
可以使用File類別建立一個檔案物件。通常使用以下3種構造方法來建立文件物件。
此建構方法透過將給定路徑名字串轉換為抽象路徑名來建立一個新File實例。
語法如下:
new File(String pathname);
其中,pathname指定路徑名稱(包含檔案名稱)。例如:
File file = new File(“d:/1.txt”);
此建構方法根據定義的父路徑和子路徑字串(包含檔案名稱)建立一個新的File物件。
語法如下:
new File(String parent,String child);
此建構方法根據Parent抽象路徑名和child路徑名稱字串建立新的File實例。
語法如下:
new File(File f,String child);
File類提供了很多方法用於獲取一些文件本身的資訊。如下表
方法| 傳回值| 說明
-------- | -----
getName() | String| 取得檔案的名稱
canReda()| boolean |判斷檔案是否為可讀的
canWrite()| boolean | 判斷檔案是否可寫入
exits()|boolean | 判斷檔案是否存在
length()|long | 取得檔案的長度(以位元組為單位)
getAbsolutePath() | String | 取得檔案的絕對路徑
getParent() | String | 取得檔案的父路徑
isFile() | boolean | 判斷文件是否存在
isDirectory() | boolean | 判斷檔案是否為一個目錄
isHidden() | boolean | 判斷檔案是否為隱藏檔案
lastModified() | long | 取得檔案最後修改時間
程式運作期間,大部分資料都在記憶體中進行操作,當程式結束或關閉時,這些資料將會消失。如果需要將資料永久保存,可使用文件輸入/輸出流與指定的文件建立連接,將所需的資料永久保存到文件中。
FileInputStream類別與FileOUtputStream類別都用來操作磁碟檔案。如果使用者的檔案讀取需求比較簡單,則可以使用FileInputString類,則該類別繼承自InputString類別。 FileOutputStream類別與FileInputStream類別對應,提供了基本的檔案寫入能力。 FileOutputStream類別是OutputStream類別的子類別。
FileInputStream類別常用的建構方法如下:
FileInputStream(String name)
FileInputStream(File file)
使用FileOutputStream類別向檔案中寫入資料與使用FileInputStream類別從檔案中將內容讀出來,都存在一點不足,即這兩個類別都只提供了對位元組或位元組數組的讀取方法。由於漢子在檔案中佔用兩個位元組,如果使用位元組流,讀取不好可能會出現亂碼現象,此時採用字元流Reader或Writer類別即可避免這種現象。
FileReader和FileWriter字元流對應了FileInputStream和FileOutputStream類別。 FileReader流依序讀取文件,只要不關閉流,每次呼叫read()方法就會依序讀取來源中其餘的內容,直到來源的末端或流被關閉。
快取是I/O的一種效能最佳化。快取流為I/O流增加了記憶體快取區。有了快取區,使得在流上執行skip()、mark()和reset()方法都成為可能。
BufferedInputStream類別可以對所有InputStream類別進行緩衝區的包裝以達到效能的最佳化。 BufferedInputStream類別有兩個建構方法:
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
#第一種建構方法來建立一個有32個位元組的快取區,第二種建構方法以指定的大小來建立快取區。
BufferedReader類別與BufferedWriter類別分別繼承Reader類別與Writer類別。這兩個類別同樣具有內部快取機制,並且可以以行為單位進行輸入/輸出。
資料輸入/輸出流(DataInputStream類別與DataOutputStream類別)允許應用程式以與機器無關的方式從底層輸入流中讀取基本Java數據類型。也就是說,當讀取一個資料時,就不必再關心這個數值應該是哪種位元組。
ZIP壓縮管理檔(ZIP archive)是一種十分典型的檔案壓縮形式,使用它可以節省儲存空間。關於ZIP壓縮的I/O實現,在Java的內建類別中提供了非常好用的相關類,所以其實現方式非常簡單。本節將介紹使用java.util.zip套件中的ZipOutputStream與ZipInputStream類別來實作檔案的壓縮/解壓縮。如要從ZIP壓縮管理文件內讀取某個文件,要先找到對應文件的「目錄進入點」(從它可知該文件在ZIP文件內的位置),才能讀取這個文件的內容。如果要將檔案內容寫入ZIP檔案內,必須先寫入對應於該檔案的“目錄進入點”,並且將要寫入檔案內容的位置移到此進入點所指的位置,然後再寫入文件內容。
Java实现了I/O数据流与网络数据流的单一接口,因此数据的压缩、网络传输和解压缩的实现比较容易。ZipEntry类产生的对象,是用来代表一个ZIP压缩文件内的进入点(entry)。ZipInputStream用来写出ZIP压缩格式的文件,所支持的包括已压缩及未压缩的进入点(entry)。
ZipOutputStream类用来写出ZIp压缩格式的文件,而且所支持的包括已压缩及未压缩的进入点(entry)。下面介绍利用ZipEntry、
ZipInputStream和ZipOutputStream3个Java类实现ZIP数据压缩方式的编程方法。
利用ZipOutputStream类对象,可将文件压缩为.zip文件。ZipOutputStream类的构造方法如下:
ZipOutputStram(OutputStream out);
ZipOutputStream类的常用方法如表所示:
方法 | 返回值 | 说明 |
---|---|---|
putNextEntry(ZipEntry e) | void | 开始写一个新的ZipEntry,并将流内的位置移至此entry所指数据的开头 |
write(byte[] b,int off,int len) | void | 将字节数组写入当前ZIP条目数据 |
finish() | void | 完成写入ZIP输出流的内容,无须关闭它所配合的OutputStream |
setComment(String comment) | void | 可设置此ZIP文件的注释文字 |
2、解压缩ZIP文件
ZipInputStream类可读取ZIP压缩格式的文件,包括已压缩和未压缩的条目(entry)。ZipInputStream类的构造方法如下:
ZipInputStream(InputStream in)
ZipInputStream类的常用方法如下表所示:
方法 | 返回值 | 说明 |
---|---|---|
read(byte[] b, int off , int len) | int | 读取目标b数组内off偏移量的位置,长度是len字节 |
available() | int | 判断是否已读完目前entry所指定的数据。已读完返回0,否则返回1 |
closeEntry() | void | 关闭当前ZIP条目并定位流以读取下一个条目 |
skip(long n) | long | 跳过当前ZIP条目中指定的字节数 |
getNextEntry() | ZipEntry | 读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头 |
createZipEntry(String name) | ZipEntry | 以指定的name参数新建一个ZipEntry对象 |
示例:假设目录“D:\TestDir1”下有两个文件夹(dir1 和 dir2)和一个文件 file1.txt 。
File[] listFiles()方法:获取该目录下的所有子目录和文件,返回File类数组。
import java.io.File; /** * 获取目录下的所有目录和文件 * @author pan_junbiao **/ public class DirFileTest { public static void main(String[] args) { File file = new File("D:\\TestDir1"); //判断目录是否存在 if (!file.exists()) { System.out.println("目录不存在"); return; } //获取文件数组 File[] fileList = file.listFiles(); for (int i = 0; i < fileList.length; i++) { //判断是否为目录 if (fileList[i].isDirectory()) { System.out.println("目录:" + fileList[i].getName()); } else { System.out.println("文件:" + fileList[i].getName()); } } } }
执行结果:
以上是Java中I/O輸入輸出實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!