天天看點

Java文法進階13-檔案、IO流

File

File是檔案和目錄路徑名的抽象表示形式,即File類是檔案或目錄的路徑,而不是檔案本身,是以File類不能直接通路檔案内容本身,如果需要通路檔案内容本身,則需要使用輸入/輸出流。

File類的對象用來表示檔案和檔案夾的對象。

如果這個路徑名對應的檔案或目錄不存在,那麼在堆中的File對象的成員變量就是預設值。

如果這個路徑名對應的檔案或目錄存在,那麼在堆中的File對象就根據這個路徑找到對應的檔案或目錄,然後将一些資訊擷取到為File對象的成員變量指派

File

 類的執行個體是不可變的;也就是說,一旦建立,

File

 對象表示的抽象路徑名将永不改變。

常用方法

方法簽名 方法功能
File(String pathName) 根據檔案、目錄的路徑名建構File對象
File(String parent, String child) 建構File對象,路徑名通過指定父目錄與子目錄方式來指定
public File(File parent,String child) 從父抽象路徑名和子路徑名字元串建立新的 File執行個體
String getName() 擷取檔案名
long length() 擷取檔案大小,無法直接擷取目錄大小,空目錄傳回0
String getPath() 擷取構造路徑
String getAbsolutePath() 擷取絕對路徑
String getCanonicalPath() 擷取規範路徑
long lastModified() 擷取檔案最後修改時間
boolean isFile() 判斷是否是檔案
boolean isDirectory() 判斷是否是目錄
boolean exists() 判斷檔案或目錄是否實際存在
boolean isHidden() 判斷是否隐藏
boolean isAbsolute() 判斷是否是絕對路徑
boolean canRead() 判斷是否可讀
boolean canWrite() 判斷是否可寫
createNewFile() 當且僅當具有該名稱的檔案尚不存在時,建立檔案
mkdir()或mkdirs() 建立目錄
delete() 删除檔案或空目錄
renameTo(File dest) 重命名檔案或目錄
String[] list() 擷取目錄裡面的檔案或子目錄,傳回String數組
File[] listFiles() 擷取目錄裡面的檔案或子目錄,傳回File數組
File[] listFiles(FileFilter filter) 根據過濾條件擷取目錄裡面的檔案或子目錄

無論該路徑下是否存在檔案或者目錄,都不影響File對象的建立。

如果檔案或目錄不存在,那麼exists()、isFile()和isDirectory()都是傳回false

調用listFiles方法的File對象,表示的必須是實際存在的目錄,否則傳回null,無法進行周遊。

絕對路徑:從盤符開始的路徑,這是一個完整的路徑。

相對路徑:相對于項目目錄的路徑,這是一個便捷的路徑,開發中經常使用。

規範路徑:所謂規範路徑名,即對路徑中的“..”等進行解析後的路徑名

建立和删除臨時檔案

  • public void deleteOnExit()

    :當退出JVM時,删除檔案,一般用于删除臨時檔案,一旦請求,無法取消。
  • public static File createTempFile(String prefix,String suffix) throws IOException在預設臨時檔案目錄中建立一個空檔案,使用給定字首和字尾生成其名稱。調用此方法等同于調用 createTempFile(prefix, suffix, null)。
    • prefix - 用于生成檔案名的字首字元串;必須至少三個字元。
    • suffix - 用于生成檔案名的字尾字元串;如果為 null,預設為 ".tmp"
  • public static File createTempFile(String prefix,String suffix,File directory)throws IOException在指定目錄中建立一個新的空檔案,使用給定的字首和字尾字元串生成其名稱。
    • directory - 将建立的檔案所在的目錄;如果使用預設臨時檔案目錄,則該參數為 null

IO

Stream即流向記憶體的是輸入流(Reader,Input),流出記憶體的輸出流(Writer,Output)。

  • 輸入流 :把資料從

    其他裝置

    上讀取到

    記憶體

    中的流。
    • 以InputStream,Reader結尾
  • 輸出流 :把資料從

    記憶體

    中寫出到

    其他裝置

    上的流。
    • 以OutputStream、Writer結尾
  • 位元組流 :以位元組為機關,讀寫資料的流。
    • 以InputStream和OutputStream結尾
  • 字元流 :以字元為機關,讀寫資料的流。
    • 以Reader和Writer結尾
  • 節點流:可以從或向一個特定的地方(節點)讀寫資料。如FileReader.
  • 處理流:是對一個已存在的流進行連接配接和封裝,通過所封裝的流的功能調用實作資料讀寫。如BufferedReader.處理流的構造方法總是要帶一個其他的流對象做參數。并且可進行多次包裝

InputStream基類:位元組輸入流

抽象類位元組流可以傳輸任意檔案類型資料

  • int read():讀一個位元組,如果流中沒有資料了,傳回-1。
  • int read(byte[] data):一次讀取多個位元組,最多讀取data.length個,把讀取的資料放到data中,從data[0]開始存儲,如果流中沒有data.length個,那麼有幾個讀取幾個,傳回實際讀取的位元組的個數。如果流中沒有資料了,傳回-1。
  • int read(byte[] data, int offset, int count):一次讀取多個位元組,最多讀取count個,把讀取的資料放到data中,從data[offset]開始存儲,如果流中沒有count個,那麼有幾個讀取幾個,傳回實際讀取的位元組的個數。如果流中沒有資料了,傳回-1。
  • void close():關閉流資源

OutputStream基類:位元組輸出流

  • public void close()

    :關閉此輸出流并釋放與此流相關聯的任何系統資源。
  • public void flush()

    :重新整理此輸出流并強制任何緩沖的輸出位元組被寫出。
  • public void write(byte[] b)

    :将 b.length位元組從指定的位元組數組寫入此輸出流。
  • public void write(byte[] b, int off, int len)

    :從指定的位元組數組寫入 len位元組,從偏移量 off開始輸出到此輸出流。
  • public abstract void write(int b)

    :将指定的位元組輸出流。

FileInputStream類

繼承InoutStream方法同上,檔案輸入流,從檔案中讀取位元組。

構造方法

  • FileInputStream(File file)

    : 通過打開與實際檔案的連接配接來建立一個 FileInputStream ,該檔案由檔案系統中的 File對象 file命名。
  • FileInputStream(String name)

    : 通過打開與實際檔案的連接配接來建立一個 FileInputStream ,該檔案由檔案系統中的路徑名 name命名。

當你建立一個流對象時,必須傳入一個檔案路徑。該路徑下,如果沒有該檔案,會抛出

FileNotFoundException

long skip(long n) :從輸入流中跳過并丢棄 n 個位元組的資料。 

讀取位元組:

read

方法,每次可以讀取一個位元組的資料,提升為int類型,讀取到檔案末尾,傳回

-1

FileOutputStream類

繼承OutputStream方法同上,檔案輸出流,用于将資料寫出到檔案。

  • public FileOutputStream(File file)

    :建立檔案輸出流以寫入由指定的 File對象表示的檔案。
  • public FileOutputStream(String name)

    : 建立檔案輸出流以指定的名稱寫入檔案。
  • public FileOutputStream(String name, boolean append):指定 String檔案名name的檔案輸出流

   public FileOutputStream(File file, boolean append):指定 File 對象的檔案輸出流,append為true表示追加資料,

false

表示清空原有資料。

當你建立一個流對象時,必須傳入一個檔案路徑。該路徑下,如果沒有這個檔案,會建立該檔案。如果有這個檔案,會清空這個檔案的資料,或指定追加。

系統中的換行:

  • Windows系統裡,每行結尾是

    回車+換行

    ,即

    \r\n

  • Unix系統裡,每行結尾隻有

    換行

    \n

  • Mac系統裡,每行結尾是

    回車

    \r

    。從 Mac OS X開始與Linux統一。

流的關閉原則:先開後關,後開先關。

Reader基類:字元輸入流

抽象類以字元為機關讀寫資料,專門用于處理文本檔案

  • public int read()

    : 讀取一個字元,如果已經到達流末尾,沒有資料可讀了,傳回-1.
  • public int read(char[] cbuf)

    : 讀取多個字元到data數組中,從data[0]開始存儲,最多讀取data.length個字元。傳回的是實際讀取的字元數。如果已經到達流末尾,沒有資料可讀了,傳回-1.
  • abstract int read(char[] data, int offset, int len):讀取多個字元到data數組中,從data[offset]開始存儲,最多讀取len個字元。傳回的是實際讀取的字元數。如果已經到達流末尾,沒有資料可讀了,傳回-1.
  • public void close()

     :關閉此流并釋放與此流相關聯的任何系統資源
  •  long skip(long n) : 跳過n字元。 

FileReader類

繼承Reader類是讀取字元檔案的便利類。構造時使用系統預設的字元編碼和預設位元組緩沖區。

  • FileReader(File file)

    : 建立一個新的 FileReader ,給定要讀取的File對象。
  • FileReader(String fileName)

    : 建立一個新的 FileReader ,給定要讀取的檔案的名稱。

當你建立一個流對象時,必須傳入一個檔案路徑。其方法同上繼承父類方法

雖然讀取了一個字元,但是會自動提升為int類型。

Writer基類:字元輸出流

抽象類表示用于寫出字元流,将指定的字元資訊寫出到目的地

  • void write(int c)

    寫入單個字元。
  • void write(char[] cbuf)

    寫入字元數組。
  • abstract void write(char[] cbuf, int off, int len)

    寫入字元數組的某一部分,off數組的開始索引,len寫的字元個數。
  • void write(String str)

    寫入字元串。
  • void write(String str, int off, int len)

    寫入字元串的某一部分,off字元串的開始索引,len寫的字元個數。
  • void flush()

    重新整理該流的緩沖。
  • void close()

    關閉此流,但要先重新整理它。

FileWriter類

繼承Writer類是寫出字元檔案的便利類。構造時使用系統預設的字元編碼和預設位元組緩沖區。

  • FileWriter(File file)

    : 建立一個新的 FileWriter,給定要讀取的File對象。
  • FileWriter(String fileName)

    : 建立一個新的 FileWriter,給定要讀取的檔案的名稱。
  • FileWriter(File file, boolean append) 根據給定的 File 對象構造一個 FileWriter 對象以及訓示是否附加寫入資料。
  • FileWriter(String fileName, boolean append) 根據給定的檔案名以及訓示是否附加寫入資料的 boolean 值來構造 FileWriter 對象。

當你建立一個流對象時,必須傳入一個檔案路徑,其方法同上繼承父類方法

未調用close方法,資料隻是儲存到了緩沖區,并未寫出到檔案中,即便是flush方法寫出了資料,操作的最後還是要調用close方法,釋放系統資源。

操作IO流的步驟

(1)建立合适的IO流的對象

(2)讀、寫

(3)關閉IO流

要麼隻關閉最外層的IO流,要是都關的話,注意順序,先關外面的再關裡面的。

緩沖流

緩沖流的基本原理,是在建立流對象時,會建立一個内置的預設大小的緩沖區數組,通過緩沖區讀寫,減少系統IO次數,進而提高讀寫的效率。

位元組緩沖流:

BufferedInputStream

BufferedOutputStream

  • public BufferedInputStream(InputStream in)

    :建立一個 新的緩沖輸入流。亦可指定緩沖區大小(InputStream in, int size) 
  • public BufferedOutputStream(OutputStream out)

    : 建立一個新的緩沖輸出流。亦可指定緩沖區大小(OutputStream out, int size) 

字元緩沖流:

BufferedReader

BufferedWriter

  • public BufferedReader(Reader in)

    :建立一個 新的緩沖輸入流。亦可指定緩沖區大小(Reader in, int sz) 
  • public BufferedWriter(Writer out)

    : 建立一個新的緩沖輸出流。亦可指定緩沖區大小(Writer out, int sz) 

字元緩沖流的特有方法。

  • BufferedReader:

    public String readLine()

    : 讀一行文字。
  • int read(char[] cbuf, int off, int len) 将字元讀入數組的某一部分從off開始讀len個。 實作了基類的抽象方法
  • BufferedWriter:

    public void newLine()

    : 寫一行行分隔符,由系統屬性定義符号。
  • void write(char[] cbuf, int off, int len) :寫入字元數組的某一部分從off開始寫len個。實作了基類的抽象方法

轉換流

解碼:位元組(看不懂的)-->字元(能看懂的)

編碼:字元(能看懂的)-->位元組(看不懂的) 

InputStreamReader類

  • InputStreamReader(InputStream in)

    : 建立一個使用系統預設字元集的字元流。
  • InputStreamReader(InputStream in, String charsetName)

    : 建立一個指定字元集的字元流。

是Reader的子類,用來解碼包裝位元組流,把位元組輸入流包裝為字元輸入流。

應用場景:讀取源為字元類型的位元組流可指定字元集解碼成字元流,以便閱讀

OutputStreamWriter類

  • OutputStreamWriter(OutputStream in)

  • OutputStreamWriter(OutputStream in, String charsetName)

是Writer的子類,用來編碼包裝位元組流,把位元組輸出流包裝為字元輸出流。

應用場景:可将要寫入的字元源為位元組流的資料轉為字元類型寫入并可按指定字元集再編碼存儲

轉換流是位元組與字元間的橋梁

Java文法進階13-檔案、IO流

資料流

 繼承位元組流可直接處理Java的基本資料類型,要求讀寫順序一一對應

DataOutputStream:資料輸出流

  • writeUTF(String)
  • writeInt(int)
  • writeDouble(double)
  • writeChar(char)
  • writeBoolean(boolean)

DataInputStream:資料輸入流

  • String readUTF()
  • int readInt()
  • double readDouble()
  • char readChar()
  • boolean readBoolean()

序列化

對象序列化,用一個位元組序列可以表示一個對象,該位元組序列包含該

對象的類型

對象中存儲的屬性

等資訊,可将位元組序列寫出到檔案。反之,該位元組序列還可以從檔案中讀取回來,重構對象,對它進行反序列化

Java文法進階13-檔案、IO流

ObjectOutputStream類

public final void writeObject (Object obj)

 : 将指定的對象寫出到OutputStream流。

  • 該類必須實作

    java.io.Serializable

    标記接口,不實作此接口的類将不會使任何狀态序列化或反序列化,會抛

    NotSerializableException

    • 如果對象的某個屬性也是引用資料類型,那麼如果該屬性也要序列化的話,也要實作

      Serializable

      接口
  • 該類的所有屬性必須是可序列化的。如果有一個屬性不需要可序列化的,則該屬性必須注明是瞬态的,使用

    transient

    關鍵字修飾。
  • 靜态變量的值不會序列化

ObjectInputStream類

如果能找到一個對象的class檔案,我們可以進行反序列化操作,調用

ObjectInputStream

讀取對象的方法:

  • public final Object readObject ()

    : 讀取一個對象到InputStream流。

另外,當JVM反序列化對象時,能找到class檔案,但是class檔案在序列化對象之後發生了修改,那麼反序列化操作也會失敗,抛出一個

InvalidClassException

異常。發生這個異常的原因如下:

  • 該類的序列版本号與從流中讀取的類描述符的版本号不比對
  • 該類包含未知資料類型

Serializable

接口給需要序列化的類,提供了一個序列版本号。

serialVersionUID

該版本号的目的在于驗證序列化的對象和對應類是否版本比對。

java.io.Externalizable接口

實作這個接口,可以自定義需要被系列化的屬性使得對象能夠被序列化,但是要求程式員重寫兩個方法:

void writeExternal(ObjectOutput out) :編寫哪些屬性需要序列化

void readExternal(ObjectInput in) :編寫哪些屬性需要反序列化

注意:讀取的順序要與寫的順序一緻,雖然可以自己決定任意屬性的輸出和讀取,但是還是建議不要輸出靜态的和transient屬性。

PrintStream類

位元組流該類調用

print

方法和

println

方法能夠友善地列印各種資料類型的值,是一種便捷的輸出方式。

System.in:InputStream類型對象

System.out:PrintStream類型對象

System.err:PrintStream類型對象

Scanner類

有多個構造方法可由多種方式生成從指定流的掃描對象,并實作了疊代器接口

  • boolean hasNextXxx(): 如果通過使用nextXxx()方法,此掃描器輸入資訊中的下一個标記可以解釋為預設基數中的一個 Xxx 值,則傳回 true。
  • Xxx nextXxx(): 将輸入資訊的下一個标記掃描為一個Xxx

新try..catch

文法格式:

try(需要關閉的資源對象的聲明){
    業務邏輯代碼
}catch(異常類型 e){
    處理異常代碼
}catch(異常類型 e){
    處理異常代碼
}
....      

它沒有finally,也不需要程式員去關閉資源對象,無論是否發生異常,都會關閉資源對象