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,也不需要程序員去關閉資源對象,無論是否發生異常,都會關閉資源對象

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章