本文分享自華為云社區《總是記不住java的IO流用法?用N個問題教你掌握java IO流》,原文作者:breakDraw ,
Java IO 體系看起來類很多,感覺很復雜,但其實是 IO 涉及的因素太多了,在設計 IO 相關的類時,撰寫者也不是從同一個方面考慮的,所以會給人一種很亂的感覺,并且還有設計模式的使用,更加難以使用這些 IO 類,所以特地對 Java 的 IO 做一個總結,
檔案API
Q: File類可以用來做目錄操作嗎?
A:可以,
File物件本身可以是目錄,呼叫file.mkdirs()即可創建目錄,
Q:直接呼叫file.delete()可以洗掉目錄嗎?
A:如果是檔案或者空目錄,可以直接洗掉,
但如果目錄中有檔案或者子目錄,則必須遞回洗掉,
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: 有哪些方法判斷給定路徑下檔案是否存在?
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
點擊關注,第一時間了解華為云新鮮技術~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/279973.html
標籤:java
