首頁  >  文章  >  Java  >  Java中I/O輸入輸出實例分析

Java中I/O輸入輸出實例分析

WBOY
WBOY轉載
2023-05-13 15:40:061456瀏覽

    前言

    在變數、陣列和物件中儲存的資料是暫時存在的,程式結束後它們就會遺失。為了能夠永久保存已建立的數據,需要將其保存在磁碟檔案中,這樣就可以在其他程式中使用它們。 Java的I/O技術可以將資料保存到文字檔案、二進位檔案甚至是ZIP壓縮檔案中,已達到永久性保存資料的要求。掌握I/O處理技術能夠提升對資料的處理能力。

    一、流概述

    流是一組有序的資料序列,根據操作的類型,可分為輸入流和輸出流兩種。 I/O(Input/Output,輸入/輸出)流提供了一條通道程序,可以使用這條通道把來源中的位元組序列送到目的地。雖然I/O流通常與磁碟檔案存取有關,但是程式的來源和目的地也可以是鍵盤、滑鼠、記憶體或顯示器視窗等。
    Java由資料流處理輸入/輸出模式,程式從指向來源的輸入流讀取來源中的數據,來源可以是檔案、網路、壓縮套件或其他資料來源。
    輸出流的指向是資料要到達的目的地,程式透過寫入資料流寫入資料把訊息到目的地。

    二、輸入/輸出流

    Java語言定義了許多類別專門負責各種方式的輸入/輸出,這類類別都被放在java.io套件中。其中,所有輸入流類別都是抽象類別InputStream(位元組輸入流)或抽象類別Reader(字元輸入流)的子類別;而所有輸出流都是抽象類別OutputStream(位元組輸出流)或抽象類別Writer(字元輸出流)的子類別。

    1、輸入流

    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文檔。

    2、輸出流

    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類別

    File類別是java.io套件中唯一代表磁碟檔案本身的物件。 File類別定義了一些與平台無關的方法來操作文件,可以透過呼叫File類別中的方法,實現創建、刪除、重新命名文件等操作。 File類別的物件主要用來取得檔案本身的一些訊息,如檔案所在的目錄、檔案的長度、檔案讀寫權限等。資料流可以將資料寫入到檔案中,檔案也是資料流最常用的資料媒體。

    1、檔案的建立與刪除

    可以使用File類別建立一個檔案物件。通常使用以下3種構造方法來建立文件物件。

    1、File(String pathname)

    此建構方法透過將給定路徑名字串轉換為抽象路徑名來建立一個新File實例。

    語法如下:

    new File(String pathname);

    其中,pathname指定路徑名稱(包含檔案名稱)。例如:

    File file = new File(“d:/1.txt”);

    2、File(String parent,String child)

    此建構方法根據定義的父路徑和子路徑字串(包含檔案名稱)建立一個新的File物件。

    語法如下:

    new File(String parent,String child);

    3、File(File f,String child)

    此建構方法根據Parent抽象路徑名和child路徑名稱字串建立新的File實例。

    語法如下:

    new File(File f,String child);

    2、取得檔案資訊

    File類提供了很多方法用於獲取一些文件本身的資訊。如下表

    方法| 傳回值| 說明
    -------- | -----
    getName() | String| 取得檔案的名稱
    canReda()| boolean |判斷檔案是否為可讀的
    canWrite()| boolean | 判斷檔案是否可寫入
    exits()|boolean | 判斷檔案是否存在
    length()|long | 取得檔案的長度(以位元組為單位)
    getAbsolutePath() | String | 取得檔案的絕對路徑
    getParent() | String | 取得檔案的父路徑
    isFile() | boolean | 判斷文件是否存在
    isDirectory() | boolean | 判斷檔案是否為一個目錄
    isHidden() | boolean | 判斷檔案是否為隱藏檔案
    lastModified() | long | 取得檔案最後修改時間

    四、檔案輸入/輸出流

    程式運作期間,大部分資料都在記憶體中進行操作,當程式結束或關閉時,這些資料將會消失。如果需要將資料永久保存,可使用文件輸入/輸出流與指定的文件建立連接,將所需的資料永久保存到文件中。

    1、FillInputStream與FileOutputStream類別

    FileInputStream類別與FileOUtputStream類別都用來操作磁碟檔案。如果使用者的檔案讀取需求比較簡單,則可以使用FileInputString類,則該類別繼承自InputString類別。 FileOutputStream類別與FileInputStream類別對應,提供了基本的檔案寫入能力。 FileOutputStream類別是OutputStream類別的子類別。
    FileInputStream類別常用的建構方法如下:

    FileInputStream(String name)
    FileInputStream(File file)

    2、FileReader和FileWriter類別

    使用FileOutputStream類別向檔案中寫入資料與使用FileInputStream類別從檔案中將內容讀出來,都存在一點不足,即這兩個類別都只提供了對位元組或位元組數組的讀取方法。由於漢子在檔案中佔用兩個位元組,如果使用位元組流,讀取不好可能會出現亂碼現象,此時採用字元流Reader或Writer類別即可避免這種現象。

    FileReader和FileWriter字元流對應了FileInputStream和FileOutputStream類別。 FileReader流依序讀取文件,只要不關閉流,每次呼叫read()方法就會依序讀取來源中其餘的內容,直到來源的末端或流被關閉。

    五、有快取的輸入/輸出流

    快取是I/O的一種效能最佳化。快取流為I/O流增加了記憶體快取區。有了快取區,使得在流上執行skip()、mark()和reset()方法都成為可能。

    1、BufferedInputStream與BufferedOutputStream類別

    BufferedInputStream類別可以對所有InputStream類別進行緩衝區的包裝以達到效能的最佳化。 BufferedInputStream類別有兩個建構方法:

    BufferedInputStream(InputStream in)
    BufferedInputStream(InputStream in,int size)

    #第一種建構方法來建立一個有32個位元組的快取區,第二種建構方法以指定的大小來建立快取區。

    2、BufferedReader與BufferedWriter類別

    BufferedReader類別與BufferedWriter類別分別繼承Reader類別與Writer類別。這兩個類別同樣具有內部快取機制,並且可以以行為單位進行輸入/輸出。

    六、資料輸入/輸出流

    資料輸入/輸出流(DataInputStream類別與DataOutputStream類別)允許應用程式以與機器無關的方式從底層輸入流中讀取基本Java數據類型。也就是說,當讀取一個資料時,就不必再關心這個數值應該是哪種位元組。

    七、ZIP壓縮輸入/輸出流

    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数据压缩方式的编程方法。

    1、压缩文件

    利用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輸入輸出實例分析

    以上是Java中I/O輸入輸出實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除