1. 程式人生 > >Java語法進階13-檔案、IO流

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

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在指定目錄中建立一個新的空檔案,使用給定的字首和字尾字串生成其名稱。

    • prefix - 用於生成檔名的字首字串;必須至少三個字元。

    • suffix - 用於生成檔名的字尾字串;如果為 null,預設為 ".tmp"

    • 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次數,從而提高讀寫的效率。

位元組緩衝流:BufferedInputStreamBufferedOutputStream

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

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

字元緩衝流:BufferedReaderBufferedWriter

  • 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的基本資料型別,要求讀寫順序一一對應

DataOutputStream:資料輸出流

  • writeUTF(String)

  • writeInt(int)

  • writeDouble(double)

  • writeChar(char)

  • writeBoolean(boolean)

DataInputStream:資料輸入流

  • String readUTF()

  • int readInt()

  • double readDouble()

  • char readChar()

  • boolean readBoolean()

序列化

物件序列化,用一個位元組序列可以表示一個物件,該位元組序列包含該物件的型別物件中儲存的屬性等資訊,可將位元組序列寫出到檔案。反之,該位元組序列還可以從檔案中讀取回來,重構物件,對它進行反序列化

 

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,也不需要程式設計師去關閉資源物件,無論是否發生異常,都會關閉資源物件

&n