摘要:Java IO 體系看起來類不少,感受很複雜,但實際上是 IO 涉及的因素太多了。在設計 IO 相關的類時,編寫者也不是從同一個方面考慮的,因此會給人一種很亂的感受,而且還有設計模式的使用,更加難以使用這些 IO 類,因此特意對 Java 的 IO 作一個總結。
本文分享自華爲雲社區《老是記不住java的IO流用法?用N個問題教你掌握java IO流》,原文做者:breakDraw 。java
Java IO 體系看起來類不少,感受很複雜,但實際上是 IO 涉及的因素太多了。在設計 IO 相關的類時,編寫者也不是從同一個方面考慮的,因此會給人一種很亂的感受,而且還有設計模式的使用,更加難以使用這些 IO 類,因此特意對 Java 的 IO 作一個總結。設計模式
文件API
Q: File類能夠用來作目錄操做嗎?數組
A:能夠。多線程
File對象自己能夠是目錄。調用file.mkdirs()便可建立目錄。函數
Q:直接調用file.delete()能夠刪除目錄嗎?編碼
A:若是是文件或者空目錄,能夠直接刪除。url
但若是目錄中有文件或者子目錄,則必須遞歸刪除。spa
private static boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); //遞歸刪除目錄中的子目錄下 for (int i=0; i<children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } // 目錄此時爲空,能夠刪除 return dir.delete(); }
Q: 有哪些方法判斷給定路徑下文件是否存在?.net
A:線程
1.File類的exists方法: file.exist(string)
File testFile = new File(testFilePath); if(!testFile .exists()) {...}
2.File類的靜態exist方法, File.exist(Path path)
Path filePath = Paths.get(testFilePath); if (Files.exists(filePath) {...}
注意靜態方法和非靜態方法的區別
字節輸入流InputStream
說一下如下這些特色對應哪些Input Stream類
- 字節數組char[] 做爲輸入源的Input Stream類是——ByteArrayInputStream
- 用文件做爲輸入源的Input Stream類是?——FileInputStream
- 用字符串做爲輸入源的是?——StringBufferInputStream
- 用於多線程之間管道通訊的輸入源是——PipeInputStream
Q: FilterInputStream是什麼?
A: 用於裝飾上面這些輸入流的,能夠疊加,每裝飾一層就至關於增長了1個功能。
InputStream inputStream = new FilterInputStream(InputStream)
如下這些特色分別對應哪些FilterInputStream?
- 裝飾後,不只可讀字符串,還可讀取例如int、long等java基本類型的是————DataInputStream
DataInputStream裏面會支持readInt、readLong等方法。 - 裝飾後,支持分批緩衝讀取讀取的是————BufferedInputStream
建立BufferedInputStream時,咱們會經過它的構造函數指定某個輸入流爲參數。BufferedInputStream會將該輸入流數據分批讀取,每次讀取一部分到緩衝中;操做完緩衝中的這部分數據以後,再從輸入流中讀取下一部分的數據。 - 其餘:
PushbackInputStream: 具備1個能回退上一個字節的緩衝區
ObjectInputStream : 通常用於反序列化讀入
LineNumberInputStream: 可跟蹤輸入流中的行號
字節輸出流OutputStream
OutputStream包含
ByteArrayOutputStream 輸出到緩衝區
FileOutputStream 寫到文件
PipedOutputStream 寫入管道
FilterOutputStream
而FilterOutputStream 包含
- DataOutputStream (能夠out.writexxx各類類型的數據,writeDouble, writeUTF, reader也同樣,能夠讀想要的數據類型)、
- PringtStream (輸出到文件用這個, 該類.println(str)便可寫入文件)
- BufferOutputString
FileOutputStream相關
Q:new FileOutputStream(name, true),這個構造裏的true參數是作什麼用的?
A:是否支持在文件末追加的意思。
默認是false,指的是覆蓋整個文本。
若是設置成true,會在要寫入的文件後面追加本次寫入的內容。
Q:
BufferOutputStream相關概念(實際上是考緩衝區是否須要刷新之類的問題)
- BufferOutputStream裏的flush()方法是作什麼的?
- BufferOutputStream調用close後,會觸發flush()來刷新緩衝區嗎?
- BufferOutputStream調用close可能會丟數據嗎?
- BufferOutputStream屢次調用close會報錯嗎?
A:
- flush把緩衝區裏的數據寫入文件,並刷新緩衝區
- close關閉此輸出流並釋放與此相關聯的任何系統資源, 會調用flush,除了flushBuffer,還會調用父類的flush。
- 不會丟數據,由於上面這條緣由。
- 屢次調用不會報錯。
Reader和Writer
Q: Reader/Writer和InputStream/OutputStream的區別?
A:
- InputStream是表示 字節輸入流 的全部類的超類
Reader是用於讀取 字符流 的抽象類
InputStream提供的是字節流的讀取,而非文本讀取,這是和Reader類的根本區別。
即用Reader讀取出來的是char數組或者String ,使用InputStream讀取出來的是byte數組。 - Reader/Writer提供兼容Unicode、面向字符的IO功能,爲了國際化
- 用reader讀取標準輸入:
BufferedReader bufr = new BufferedReader(new InputStreamReader(http://System.in)); - 用Writer進行標準輸出:
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
設置編碼:
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8"); BufferedReader read = new BufferedReader(isr);
序列化問題
Q: 對某對象進行序列化時, 如何讓裏面某個敏感成員不被序列化?
A:
- 方法一:可以使用transient關鍵字處理那個敏感成員
- 方法二:能夠經過覆蓋Serializable接口的writeObject和readObject來實現序列化, 可是方法簽名必須是private void writeObject(ObjetOutputStream stream) throw IOException;
- 方法三: 實現Externalizable接口,可自定義實現writeExternal以及readExternal方法
Q: Externalizable和Serializable哪一個快?
A: Externalizable更快。
Q: Externalizable須要產生序列化ID嗎?
A: 採用Externalizable無需產生序列化ID(serialVersionUID)~而Serializable接口則須要
參考資料
https://blog.csdn.net/qq_26222859/article/details/50994113
https://blog.csdn.net/weixin_44117272/article/details/90767074