在閱讀Java I/O的執行個體之前我們必須清楚一些概念,我們先看看Java I/O的類結構圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISOxkjNzgTN1EjNwMDM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
Java I/O主要以流的形式進行讀寫資料。
流是一組有順序的,有起點和終點的位元組集合,是對資料傳輸的總稱或抽象。即資料在兩裝置間的傳輸稱為流,流的本質是資料傳輸,根據資料傳輸特性将流抽象為各種類,友善更直覺的進行資料操作。
根據處理資料的資料類型的不同可以分為:字元流和位元組流。
字元流和位元組流的主要差別:
1.位元組流讀取的時候,讀到一個位元組就傳回一個位元組; 字元流使用了位元組流讀到一個或多個位元組(中文對應的位元組數是兩個,在UTF-8碼表中是3個位元組)時。先去查指定的編碼表,将查到的字元傳回。
2.位元組流可以處理所有類型資料,如:圖檔,MP3,AVI視訊檔案,而字元流隻能處理字元資料。隻要是處理純文字資料,就要優先考慮使用字元流,除此之外都用位元組流。
3.實際上位元組流在操作時本身不會用到緩沖區(記憶體),是檔案本身直接操作的,而字元流在操作時使用了緩沖區,通過緩沖區再操作檔案。
下面我們以檔案操作作為執行個體進一步了解。
之前提到過“隻要是處理純文字資料,就要優先考慮使用字元流,除此之外都用位元組流”。是以本字元流操作執行個體是操作txt檔案。對其進行讀寫操作。
2.1、一些概念
此前,我們需要了解一些概念。
Java采用16位的Unicode來表示字元串和字元的。在寫入字元流時我們都可以指定寫入的字元串的編碼。
這裡部落客貼出字元流類圖結構,友善猿友閱讀:
在檔案操作的時候我們主要使用到FileReader和FileWriter或BufferedReader和BufferedWriter。
從類結構圖來看:
FileReader是InputStreamReader的子類,而InputStreamReader是Reader的子類;
FileWriter是OutputStreamWriter的子類,而OutputStreamWriter則是Writer的子類。
2.2、FileReader和BufferedReader的使用
FileReader的常用構造包括以下兩種:
(1)FileReader(String fileName):根據檔案名建立FileReader對象。
(2)FileReader(File file):根據File對象建立FileReader對象。
FileReader的常用方法包括以下幾種:
(1)int read():讀取單個字元。傳回字元的整數值,如果已經到達檔案尾,則傳回-1.
(2)int read(char[] cbuf):将字元讀入cbuf字元數組。傳回讀取到的字元數,如果已經到達檔案尾,則傳回-1.
(3)int read(char[] cbuf,int off,int len):将讀取到的字元存放到cbuf字元數組從off辨別的偏移位置開始處,最多讀取len個字元。
BufferedReader有以下兩種構造方法:
(1)BufferedReader(Reader in):根據in代表的Reader對象建立BufferReader執行個體,緩沖區大小采用預設值。
(2)BufferedReader(Reader in,int sz):根據in代表的Reader對象建立BufferedReader執行個體,緩沖區大小采用指定sz值。
BufferedReader的常用方法包括以下幾種:
(1)int read():傳回字元的整數值,如果已經到達檔案尾,則傳回-1.
(2)int read(char[], int, int):将讀取到的字元存放到cbuf字元數組從off辨別的偏移位置開始處,最多讀取len個字元。
(3)String readLine():讀取一文本行。該方法遇到以下字元或者字元串認為目前行結束:‘\n’(換行符),’\r’(回車符),’\r\n’(回車換行)。傳回值為該行内容的字元串,不包含任何行終止符,如果已到達流末尾,則傳回null。
代碼執行個體:
上面代碼用到finally,關于finally雖然與I/O無關,不過這裡還是說一下:
1、不管有木有出現異常,finally塊中代碼都會執行;
2、當try和catch中有return時,finally仍然會執行;
3、finally是在return後面的表達式運算後執行的(此時并沒有傳回運算後的值,而是先把要傳回的值儲存起來,管finally中的代碼怎麼樣,傳回的值都不會改變,任然是之前儲存的值),是以函數傳回值是在finally執行前确定的;
4、finally中最好不要包含return,否則程式會提前退出,傳回值不是try或catch中儲存的傳回值。
readerTest.txt文本内容:
執行結果:
2.3、FileWriter和BufferWriter的使用
FileWriter的常用構造有以下四種:
(1)FileWriter(String fileName):根據檔案名建立FileWriter對象。
(2)FileWriter(String fileName,boolean append):根據檔案名建立FileWriter對象,append參數用來指定是否在原檔案之後追加内容。
(3)FileWriter(File file):根據File對象建立FileWriter對象。
(4)FileWriter(File file,boolean append):根據File對象建立FileWriter對象,append參數用來指定是否在原檔案之後追加内容。
FileWriter的常用方法包括以下幾種:
(1)void writer(int c):向檔案中寫入正整數c代表的單個字元。
(2)void writer(char[] cbuf):向檔案中寫入字元數組cbuf。
(3)void writer(char[] cbuf,int off, in len):向檔案中寫入字元數組cbuf從偏移位置off開始的len個字元。
(4)void writer(String str):向檔案中寫入字元串str,注意此方法不會在寫入完畢之後自動換行。
(5)void writer(String str,int off,int len):向檔案中寫入字元串str的從位置off開始、長度為len的一部分子串。
(6)Writer append(char c):向檔案中追加單個字元c。
(7)Writer append(CharSequence csq):向檔案中追加csq代表的一個字元序列。CharSequence是從JDK1.4版本開始引入的一個接口,代表字元值的一個可讀序列,此接口對許多不同種類的字元序列提供統一的隻讀通路。
(8)Writer append(CharSequence csq,int start,int end):向檔案中追加csq字元序列的從位置start開始、end結束的一部分字元。
(9)void flush():重新整理字元輸出流緩沖區。
(10)void close():關閉字元輸出流。
BufferedWriter也擁有如下兩種形式的構造方法:
(1)BufferedWriter(Writer out): 根據out代表的Writer對象建立BufferedWriter執行個體,緩沖區大小采用預設值。
(2)BufferedWriter(Writer out,int sz):根據out代表的Writer對象建立BufferedWriter執行個體,緩沖區大小采用指定的sz值。
BufferedWriter的常用方法包括以下幾種:
(1)void close() :關閉字元輸出流。
(2)void flush() :重新整理字元輸出流緩沖區。
(3)void newLine(): 寫入文本行。
(4)void write(char[] cbuf, int offset, int count) :向檔案中寫入字元數組cbuf從偏移位置off開始的len個字元。
(5)void write(int oneChar) :寫入單個字元。
(6)void write(String str, int offset, int count) :向檔案中寫入字元串str的從位置off開始、長度為len的一部分子串。
(7)以上的方法都是重寫了Writer的,還有繼承自java.io.Writer 的方法:Writer append(char c)、Writer append(CharSequence csq)、Writer append(CharSequence csq, int start, int end)、void write(char[] cbuf)、write(String str)等方法。
我們先把readerTest.txt檔案的内容清空,運作結果如下(不清空也行,隻是運作結果部落客的不一樣):
3.1、執行個體之前
再次聲明之前提到過的“隻要是處理純文字資料,就要優先考慮使用字元流,除此之外都用位元組流”。
這裡部落客貼出位元組流類圖結構,友善猿友閱讀:
下面我們依舊以檔案讀寫為例。
3.2、FileInputStream的使用
FileInputStream的構造方法:
(1)FileInputStream(File file) :通過打開一個到實際檔案的連接配接來建立一個 FileInputStream,該檔案通過檔案系統中的 File 對象 file 指定。
(2)FileInputStream(FileDescriptor fdObj) :通過使用檔案描述符 fdObj 建立一個 FileInputStream,該檔案描述符表示到檔案系統中某個實際檔案的現有連接配接。
(3)FileInputStream(String name) 通過打開一個到實際檔案的連接配接來建立一個 FileInputStream,該檔案通過檔案系統中的路徑名 name 指定。
FileInputStream的常用方法:
(1)int available():傳回下一次對此輸入流調用的方法可以不受阻塞地從此輸入流讀取(或跳過)的估計剩餘位元組數。
(2)void close():關閉此檔案輸入流并釋放與此流有關的所有系統資源。
(3)protected void finalize():確定在不再引用檔案輸入流時調用其 close 方法。
(4)FileChannel getChannel():傳回與此檔案輸入流有關的唯一 FileChannel 對象。
(5)FileDescriptor getFD():傳回表示到檔案系統中實際檔案的連接配接的 FileDescriptor 對象,該檔案系統正被此 FileInputStream 使用。
(6)int read():從此輸入流中讀取一個資料位元組。
(7)int read(byte[] b):從此輸入流中将最多 b.length 個位元組的資料讀入一個 byte 數組中。
(8)int read(byte[] b, int off, int len):從此輸入流中将最多 len 個位元組的資料讀入一個 byte 數組中。
(9)long skip(long n):從輸入流中跳過并丢棄 n 個位元組的資料。
readerTest.txt内容:
運作結果:
3.3、FileOutputStream 的使用
FileOutputStream的構造方法:
(1)FileOutputStream(File file) :建立一個向指定 File 對象表示的檔案中寫入資料的檔案輸出流。
(2)FileOutputStream(File file, boolean append) :建立一個向指定 File 對象表示的檔案中寫入資料的檔案輸出流。append參數用來指定是否在原檔案之後追加内容。
(3)FileOutputStream(FileDescriptor fdObj) :建立一個向指定檔案描述符處寫入資料的輸出檔案流,該檔案描述符表示一個到檔案系統中的某個實際檔案的現有連接配接。
(4)FileOutputStream(String name) :建立一個向具有指定名稱的檔案中寫入資料的輸出檔案流。
(5)FileOutputStream(String name, boolean append) : 建立一個向具有指定 name 的檔案中寫入資料的輸出檔案流。append參數用來指定是否在原檔案之後追加内容。
FileOutputStream的常用方法:
(1)void close() :關閉此輸出流并釋放與此流有關的所有系統資源。
(2)void flush() :重新整理此輸出流并強制寫出所有緩沖的輸出位元組。
(3)void write(byte[] b) :将 b.length 個位元組從指定的位元組數組寫入此輸出流。
(4)void write(byte[] b, int off, int len) :将指定位元組數組中從偏移量 off 開始的 len 個位元組寫入此輸出流。
(6)abstract void write(int b) :将指定的位元組寫入此輸出流。