日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【图解Java】这下可以真的弄懂Java IO了~

發布時間:2025/3/20 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【图解Java】这下可以真的弄懂Java IO了~ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 寫在前面
    • Java IO(Stream)
      • 一、IO流的分類和概念
        • 1.1 流的分類
        • 流的原理和解析
      • 二、IO流的常見用法
        • 2.1 這里是輸入流的一些讀取方法
        • 2.2 提供的一些移動指針的方法
        • 2.3 這里是輸出流的一些寫出方法
        • 2.4 緩沖流的使用
        • 2.5 轉換流的使用
        • 2.6 對象流的使用
      • 三、何為NIO,和傳統Io有何區別?
      • 四、在開發中正確使用Io流
      • 五、總結(圖解)
        • 5.1 節點流
        • 5.2 字符流
      • 六、補充一些面試題
      • 參考資料(同致謝!)

寫在前面

本文是建立在網上各類關于IO博客、學習中的實體書以及自己的使用經驗總結的。參考文獻在文末給出,若有原創作者自己的內容不愿意在本文中發布,請私信告知。

Java IO(Stream)

1.什么是流?

抽象的來說:流是一種在Java中對文件操作的形式,是Java內存中的一組有序數據序列。

具體的來說:Java程序將數據從源(文件、內存、鍵盤、網絡)讀入到內存中,形成了流,然后將這些流還可以寫到另外的目的地(文件、內存、控制臺、網絡)。

2.為什么稱為流?

之所以稱為流,是因為這個數據序列在不同時刻可能代表不同的數據來源。

3.為什么使用流?

流提供了一種讓我們可以在比集合更高的概念級別上指定計算的數據視圖 。通過使用流,我們可以說明想要完成什么任務,而不是說明如何去實現它

一、IO流的分類和概念

備注:①按列是依據操作方向(輸入輸出)出來分類;②按行是依據操作對象(字符字節)來分類;③帶紅框的是節點流,意味外面的處理流

分類字節輸入流字節輸出流字符輸入流字符輸出流
抽象基類InputStreamOutputStreamReaderWriter
訪問文件FileInputStreamFileOutputStreamFileReaderFileWriter
訪問數組ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
訪問管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
訪問字符串StringReaderStringWriter
緩沖流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
轉換流InputStreamReaderOutputStreamWriter
對象流ObjectInputStreamObjectOutputStream
抽象基類FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流PrintStreamPrintWriter
推回輸入流PushbackInputStreamPushbackReader
特殊流DataInputStreamDataOutputStream

【帶著問題去思考】

  • 為什么轉換流只存在轉為字符型
  • 為什么對象流只存在字節型
  • 處理流和節點流的關系是什么
  • IO可以處理哪些類型
  • 1.1 流的分類

    按輸入輸出方向劃分

    • 輸入流:數據外存→內存
    • 輸出流:數據內存→外存

    按處理單元劃分(可以想成字節處理ASCII碼很強,字符流處理文本)

    • 字節流:1Byte
    • 字符流:2Byte

    按是否直接作用于外部數據可以劃分

    • 節點流:可以從一個特定的設備讀寫數據的流
      • 特點:當使用節點流進行輸入輸出時,程序直接連接到實際數據,和實際的輸入輸出節點連接。沒有節點流是無法讀到數據的
    • 處理流:對一個已存在的類進行連接和封裝,封裝后的劉實現讀寫功能。
      • 特點:①程序不會與數據直接接觸;②處理流可以重復使用,只要處理流不變,程序的輸入輸出就可以不變

    其中字節流和字符流、輸入流和輸出流圖解如下。

    流的原理和解析

    ? 對于InputStream和Reader而言,它們把輸入設備抽象成為一個”水管“,這個水管的每個“水滴”依次排列:
    ? 從下圖可以看出,字節流和字符流的處理方式其實很相似,只是它們處理的輸入/輸出單位不同而已。輸入流使用隱式的記錄指針來表示當前正準備從哪個“水滴”開始讀取,每當程序從InputStream或者Reader里面取出一個或者多個“水滴”后,記錄指針自定向后移動;除此之外,InputStream和Reader里面都提供了一些方法來控制記錄指針的移動。

    • 性能的提高:主要以增加的方式來提供輸入和輸出的效率
    • 操作的便捷:處理流可能提供了一系列便捷的方法來一次輸入輸出大批量的內容,而不是輸入/輸出一個或者多個水滴。

    處理流可以套接在任何已存在的流的基礎之基礎上,這就允許Java采用相同的代碼,透明的方式來訪問不同的輸入和輸出設備的數據流。

    二、IO流的常見用法

    這是輸入輸出流(節點流)的程序流程模型

    2.1 這里是輸入流的一些讀取方法

    前面說過InputStream和Reader都是抽象類,本身不能創建實例,但它們分別有一個用于讀取文件的輸入流:FileInputStream和FileReader,它們都是節點流——會直接和指定文件關聯。下面程序示范使用FileInputStream和FileReader。

    (1)在InputStream里面包含如下3個方法。

    • int read():從輸入流中讀取單個字節,返回所讀取的字節數據(字節數據可直接轉換為int類型)。
    • int read(byte[] b):從輸入流中最多讀取(b.length)個字節的數據,并將其直接存儲在字節數組b中,返回實際讀取的字節數。
    • int read(byte[] b,int off,int len): 從輸入流中最多讀取 len 個字節的數據,并將其存儲在數組b中,放入數組b中時。off并不是從數組起點開始,而是從off位置開始,返回實際讀取的字節數。

    ==結果:==上述三種方法的結果基本一致:讀取到緩沖區的總**字節**數,如果沒有更多的數據,因為已經到達流的末尾,那么 -1 。 如果在讀取中線問題,則拋出IOException。(如果用如下代碼讀取字節型,可以進行;但是含有中文字符,會輸出亂碼)

    public class InputStreamTest {public static void main(String[] args) throws IOException{//創建流FileInputStream fileInputStream = null;try {fileInputStream = new FileInputStream("src/配置填寫說明.docx");//創建一個長度為1024的水管byte[] b = new byte[1024];//用于保存的實際字節數int hasReader = 0;//使用循環來取水的過程while((hasReader = fileInputStream.read(b))>0){System.out.println(new String(b,0,hasReader));}} catch (FileNotFoundException e) {e.printStackTrace();}finally {fileInputStream.close();}} }

    (2)在Reader中包含如下3個方法。

    • int read():從輸入流中讀取單個字符,返回所讀取的字符數據(字節數據可直接轉換為int類型)。——但這個方法有一個限制,就是:字符讀取,作為0到65535( 0x00-0xffff ,即2的16次方)范圍內的整數,如果已經達到流的末尾,則為-1。
    • int read(char[] b):從輸入流中最多讀取b.length個字符的數據,并將其存儲在字節數組b中,返回實際讀取的字符數。
    • int read(char[] b,int off,int len): 從輸入流中最多讀取len個字符的數據,并將其存儲在數組b中,放入數組b中時,并不是從數組起點開始,而是從off位置開始,返回實際讀取的字符數。

    ==結果:==上述三種方法的結果基本一致:讀取到緩沖區的總**字符**數,如果沒有更多的數據,因為已經到達流的末尾,那么 -1 。 如果在讀取中線問題,則拋出IOException。

    public class ReaderTest {public static void main(String[] args) throws IOException {//創建一個流FileReader fileReader = null;String file = "src/配置填寫說明.docx";//選擇需要讀取的對象try {fileReader = new FileReader(file);//創建一個長度為1024的字符水管char[] c = new char[204800];//用于保存的實際字符數int hasReader = 0;while((hasReader = fileReader.read(c))>0){System.out.println(new String(c,0,hasReader));}} catch (FileNotFoundException e) {e.printStackTrace();}finally {//關閉流fileReader.close();}} }

    【總結】通過比較可以得到如下結論:

  • 以上是兩種面向不同的處理單元(InputStream是面向字節流的,Reader是面向字符流的)

  • 二者的方法是十分相似的

  • 二者都需要拋出IOException

  • 單純使用這InputStream方法讀取數據會有亂碼問題(即讀取中文的時候有亂碼問題,比如“水管不夠長”)

    我們知道,一個中文字符是占據兩個字節的,InputStream中的字節數組不夠,在讀取讀取最后一個字節是,發現正好是中文字符的一半。由于數據還沒有讀完且數組還有一個字節的空位,所以read會繼續往后讀。讀取中文字符的一半也就出現了亂碼

  • 2.2 提供的一些移動指針的方法

    InputStream和Reader共用的:

    • void mark(int readAheadLimit):在記錄指針當前位置記錄一個標記(mark)。
    • boolean markSupported():判斷此輸入流是否支持mark()操作,即是否支持記錄標記。
    • void reset():將此流的記錄指針重新定位到上一次記錄標記(mark)的位置。
    • long skip(long n):記錄指針向前移動n個字節/字符。

    2.3 這里是輸出流的一些寫出方法

    OutputStream和Writer的用法也非常相似,兩個流都提供了如下三個方法:

    • void write(int c):將指定的字節/字符輸出到輸出流中,其中c即可以代表字節,也可以代表字符。
    • void write(byte[]/char[] buf):將字節數組/字符數組中的數據輸出到指定輸出流中。
    • void write(byte[]/char[] buf, int off,int len ):將字節數組/字符數組中從off位置開始,長度為len的字節/字符輸出到輸出流中。

    因為字符流直接以字符作為操作單位,所以Writer可以用字符串來代替字符數組,即以String對象作為參數。Writer里面還包含如下兩個方法。

    • void write(String str); 將str字符串里包含的字符輸出到指定輸出流中。
    • void write (String str, int off, int len); 將str字符串里面從off位置開始,長度為len的字符輸出到指定輸出流中。

    FileOutputStream/FileWriter是Io中的文件輸出流,下面介紹這兩個類的用法。

    FileOutputStream的用法:

    public class OutputStreamTest {public static void main(String[] args) throws IOException {//創建一個輸入流和輸出流FileInputStream fis = null;FileOutputStream fos = null;try {//找到水源//讀取數據fis = new FileInputStream("src/main/resources/data/配置填寫說明.txt");//寫到一個新文件中fos = new FileOutputStream("src/main/resources/data/OutputStream.txt");//創建一根水管byte[] b = new byte[1024];int hasByte = 0;while((hasByte = fis.read(b)) > 0){fos.write(b,0,hasByte);}} catch (FileNotFoundException e) {e.printStackTrace();}finally {fis.close();fos.close();}} }

    運行程序,可以看到在輸出目錄會出現OutputStream.txt文件,里面的內容與InputStream.txt內容沒有差別,

    注: 使用java的io流執行輸出時,不要忘記關閉輸出流,關閉輸出流除了可以保證流的物理資源被回收之外,可能還可以將輸出流緩沖區中的數據flush到物理節點中里(因為在執行close()方法之前,自動執行輸出流的flush()方法)。java很多輸出流默認都提供了緩存功能,其實我們沒有必要刻意去記憶哪些流有緩存功能,哪些流沒有,只有正常關閉所有的輸出流即可保證程序正常。

    【總結】而FileWrite與FileOutputStream用法是一樣的,①這兩者這是操作對象的單位不同而已。另外,②在“水管”不夠長的情況下,若讀取以字符為單位的文件或者其他內容時,FileOutputStream獲取會出現亂碼

    2.4 緩沖流的使用

    (1)緩沖流是什么?

    緩沖流是處理流的一種。它依賴于節點流(也就是直接作用到輸入輸出對象的IO流),它令節點流具有1個緩沖區,顯著減少與外部設備的IO次數, 而且提供一些額外的方法。這里為什么說設置緩沖區可以減少與外部設備IO次數并提高效率在操作系統中會說到。涉及到中斷、總線和一些解決機制。

    (2)為什么使用緩沖流

  • 減少設備與IO交互的次數(提升性能),內存和外存的交互是非常消耗時間的

  • 使用一些緩沖流的額外的方法,提高編程效率。

  • 緩沖流有預讀機制,比起使用緩沖數組的緩沖效果更加明顯,如果處理一些大數據文件,或者網絡傳輸, 使用緩沖流的效果會更加好!

  • (3)如何使用緩沖流

    緩沖流和前面幾個節點流類似,就是在節點流的基礎上套一層緩沖處理流而已。然后用這個緩沖流去完成各類操作。

    緩沖流的使用(BufferedInputStream/BufferedReader, BufferedOutputStream/BufferedWriter):
    下面介紹字節緩存流的 用法(字符緩存流的用法和字節緩存流一致就不介紹了):

    public class BufferStream {public static void main(String[] args) throws IOException {//創建輸入流、輸出流、緩沖輸入流、緩沖輸出流FileInputStream fis = null;FileOutputStream fos = null;BufferedInputStream bis = null;BufferedOutputStream bos = null;try {//找到水源fis = new FileInputStream("IO/src/main/resources/data/InputStream.txt");fos = new FileOutputStream("IO/src/main/resources/data/BufferedOutputStream.txt");//使用緩沖流,當時由于它是處理流,所以要建立在節點流之上bis = new BufferedInputStream(fis);bos = new BufferedOutputStream(fos);//建立水管byte[] b = new byte[1024];int hasRead = 0;while((hasRead =bis.read(b))>0){bos.write(b,0,hasRead);}} catch (FileNotFoundException e) {e.printStackTrace();}finally {bis.close();bos.close();}} }

    可以看到使用字節緩存流讀取和寫入數據的方式和文件流(FileInputStream,FileOutputStream)并沒有什么不同,只是把處理流套接到文件流上進行讀寫。緩存流的原理下節介紹。

    上面代碼中我們使用了緩存流和文件流,但是我們只關閉了緩存流。這個需要注意一下,當我們使用處理流套接到節點流上的使用的時候,只需要關閉最上層的處理就可以了。java會自動幫我們關閉下層的節點流。

    2.5 轉換流的使用

    (1)什么是轉換流?

    轉換流就是用來實現將字節流轉化成字符流,字符流與字節流之間的橋梁。

    (2)為什么要使用轉換流?

    存在將字節流轉換成字符流的轉換流,因為字符流操作文本更簡單;不存在把字符流轉換成字節流的轉換流,因為沒有必要。

    (3)如何使用轉換流?

    與前面類似的,轉換流也有兩種,分別對應了輸入和輸出:InputStreamReader/OutputStreamWriter。當我們遇到不大方便的輸入、輸出類型的時候,比如在讀取的時候,要將字節輸入流轉換為字符輸入流,就需要采用轉換流InputStreamReader將其包裝成BufferedReader,利用BufferedReader的readLine()方法可以一次讀取一行內容。其中,OutputStreamWriter用于將字節輸出流轉換為字符輸出流。如下代碼所示:

    public class InputStreamReaderTest {public static void main(String[] args) throws IOException {//創建流InputStreamReader isr = null;OutputStreamWriter osw = null;BufferedReader br = null;//BufferedWriter bw = new BufferedWriter(new FileWriter("IO/src/main/resources/data/BufferedWriter.txt"));//上面是寫出到本地,下面是寫出到控制臺BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));try {//從鍵盤讀入數據并寫出到本地,此處已經把節點流轉為處理流了//isr = new InputStreamReader(new FileInputStream(System.in));//上面是從鍵盤讀入數據,下面是從文件中讀入數據isr = new InputStreamReader(new FileInputStream("IO/src/main/resources/data/InputStream.txt"));//將轉換流嵌套在緩沖流內,保證IO效率br = new BufferedReader(isr);String line = null;while ((line = (br.readLine())) != null) {if("\r".equals(line)){break;}bw.write(line);}}catch(FileNotFoundException e){e.printStackTrace();}finally {br.close();bw.close();}} }

    上面程序將System.in包裝成BufferedReader,BufferedReader流具有緩存功能,在代碼的注釋也已經提到了,它可以一次讀取一行文本(這也是一種十分好用的方法,有些IO類是沒有這種方法的)——在設計時,以換行符為標志,如果它沒有讀到換行符,則程序堵塞,等到讀到換行符為止。運行上面程序可以發現這個特征,當我們在控制臺執行輸入時,只有按下回車鍵,程序才會打印出剛剛輸入的內容。同樣的,從文件中讀入數據也是這樣一種狀態,從文件中讀入數據,同樣的用BufferedReader包裝,在讀取完文件中每行數據時,就在控制臺輸出。

    2.6 對象流的使用

    (1)什么是對象流?

    對象流就是將Java對象序列化(持久化),并保存到本地磁盤文件,或者將磁盤文件反序列化成Java對象。

    (2)為什么使用對象流?

    用于寫入對象的信息和讀取對象的信息,使得對象持久化。

    【注意】為什么要做這些操作呢?請看實例下面的解釋

  • 如果想將一個對象寫入到磁盤中,那么對象所屬的類必須要進行序列化,實現Serializable 接口,Serializable接口沒有任何方法,是一個標記接口
  • 如果對象所屬的類的成員變量發生改變,你在讀取原來的對象是就會報錯,如果想要解決報錯,保證serialVersionUID是唯一
  • 如果你不想將某些信息存入到磁盤 就可以同過transient關鍵字修飾成員變量
  • 如果一個類中引用了另外的一個類,那么另外的這個類也要實現Serializable接口。
  • (3)如何使用對象流?

    (ObjectInputStream/ObjectOutputStream)

    序列化:將一個對象寫入到本地文件中

    反序列化:將一個本地文件中的對象讀取出來

    //創建要寫入磁盤的類,這個類需要實現接口 Serializable(可系列化的) class Student implements Serializable{// 在這里保證了serialVersionUID 的唯一性,防止屬性變量的臨時改變,從而造成寫入id與讀取id不同private static final long serialVersionUID = 1L;int id ; //額外需要添加一個屬性private String name;private int age;private String gender;public Student(){}public Student(String name,int age,String gender){this.name = name;this.age = age;this.gender = gender;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;} } public class ObjectIOStream {public static void main(String[] args) throws ClassNotFoundException {createObj();readObj();}public static void createObj() {try {//創建寫入磁盤的位置,并用ObjectOutputStream流處理ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO/src/main/resources/data/ObjectIOStream.txt"));//創建對象Student ffideak = new Student("ffideal", 22, "男");//向目標路徑文件寫入對象oos.writeObject(ffideak);oos.close();} catch (IOException e) {e.printStackTrace();}}public static void readObj() throws ClassNotFoundException {try {//找到讀取對象的位置ObjectInputStream ois = new ObjectInputStream(new FileInputStream("IO/src/main/resources/data/ObjectIOStream.txt"));Student ffideal = (Student) ois.readObject();System.out.println("name:"+ffideal.getName()+",age:"+ffideal.getAge()+",gendar:"+ffideal.getGender());ois.close();} catch (IOException e) {e.printStackTrace();}} }

    【解釋】

    1.為什么要使用Serializable接口?

    說到對象序列化,必須要講到Serializable接口。Java對象所屬的類必須實現Serializable接口。實現這個接口不必重寫任何方法,其只作為可序列化的標識。

    在這里建議:每一個實現Serializable接口的對象類,需要顯示添加一個常數serialVersionUID,表明該類的版本。如果不添加該常數,對象序列化時會根據對象類的信息計算出默認的serialVersionUID的值。

    serialVersionUID就像我們的身份證一樣,每次序列化時,java編譯器會根據serialVersionUID確認java對象類。這個時候,serialVersionUID的值就會出現不同(前一次寫入不一樣的serialVersionUID值),那么在反序列化時,如果serialVersionUID不一致,會拋出InvalidClassException異常。

    使用對象流的一些注意事項
    1.讀取順序和寫入順序一定要一致,不然會讀取出錯。
    2.在對象屬性前面加transient關鍵字,則該對象的屬性不會被序列化。

    三、何為NIO,和傳統Io有何區別?

    我們使用InputStream從輸入流中讀取數據時,如果沒有讀取到有效的數據,程序將在此處阻塞該線程的執行。其實傳統的輸入里和輸出流都是阻塞式的進行輸入和輸出。 不僅如此,傳統的輸入流、輸出流都是通過字節的移動來處理的(即使我們不直接處理字節流,但底層實現還是依賴于字節處理),也就是說,面向流的輸入和輸出一次只能處理一個字節,因此面向流的輸入和輸出系統效率通常不高。
    ? ? 從JDk1.4開始,java提供了一系列改進的輸入和輸出處理的新功能,這些功能被統稱為新IO(NIO)。新增了許多用于處理輸入和輸出的類,這些類都被放在java.nio包及其子包下,并且對原io的很多類都以NIO為基礎進行了改寫。新增了滿足NIO的功能。
    ? ? NIO采用了內存映射對象的方式來處理輸入和輸出,NIO將文件或者文件的一塊區域映射到內存中,這樣就可以像訪問內存一樣來訪問文件了。通過這種方式來進行輸入/輸出比傳統的輸入和輸出要快的多。

    JDk1.4使用NIO改寫了傳統IO后,傳統IO的讀寫速度和NIO差不了太多。

    四、在開發中正確使用Io流

    了解了java io的整體類結構和每個類的一下特性后,我們可以在開發的過程中根據需要靈活的使用不同的Io流進行開發。下面是我整理2點原則:

    • 如果是操作二進制文件那我們就使用字節流,如果操作的是文本文件那我們就使用字符流。
    • 盡可能的多使用處理流,這會使我們的代碼更加靈活,復用性更好。

    五、總結(圖解)

    5.1 節點流

    1) 輸入字節流InputStream

    • **ByteArrayInputStream、StringBufferInputStream、FileInputStream:**是三種基本的介質流,它們分別從Byte 數組、StringBuffer、和本地文件中讀取數據。
    • PipedInputStream: 是從與其它線程共用的管道中讀取數據。PipedInputStream的一個實例要和PipedOutputStream的一個實例共同使用,共同完成管道的讀取寫入操作。主要用于線程操作。
    • DataInputStream: 將基礎數據類型讀取出來
    • ObjectInputStream 和所有 FilterInputStream 的子類都是裝飾流(裝飾器模式的主角)。

    2)輸出字節流OutputStream:

    • ByteArrayOutputStreamFileOutputStream: 是兩種基本的介質流,它們分別向Byte 數組、和本地文件中寫入數據。
    • PipedOutputStream: 是向與其它線程共用的管道中寫入數據。
    • DataOutputStream: 將基礎數據類型寫入到文件中
    • ObjectOutputStream: 和所有 FilterOutputStream 的子類都是裝飾流。

    節點流的輸入和輸出類結構圖

    5.2 字符流

    3)字符輸入流Reader::

    • FileReader、CharReader、StringReader 是三種基本的介質流,它們分在本地文件、Char 數組、String中讀取數據。
    • PipedReader:是從與其它線程共用的管道中讀取數據
    • BufferedReader :加緩沖功能,避免頻繁讀寫硬盤
    • InputStreamReader: 是一個連接字節流和字符流的橋梁,它將字節流轉變為字符流。

    4)字符輸出流Writer:

    • StringWriter:向String 中寫入數據。
    • CharArrayWriter:實現一個可用作字符輸入流的字符緩沖區
    • PipedWriter:是向與其它線程共用的管道中寫入數據
    • BufferedWriter : 增加緩沖功能,避免頻繁讀寫硬盤。
    • PrintWriterPrintStream 將對象的格式表示打印到文本輸出流。 極其類似,功能和使用也非常相似
    • OutputStreamWriter: 是OutputStream 到Writer 轉換的橋梁,它的子類FileWriter 其實就是一個實現此功能的具體類(具體可以研究一SourceCode)。功能和使用和OutputStream 極其類似,后面會有它們的對應圖。

    字符流的輸入和輸出類結構圖

    六、補充一些面試題

    1. 什么是IO流?
    它是一種數據的流從源頭流到目的地。比如文件拷貝,輸入流和輸出流都包括了。輸入流從文件中讀取數據存儲到進程(process)中,輸出流從進程中讀取數據然后寫入到目標文件。

    2. 字節流和字符流的區別。
    字節流在JDK1.0中就被引進了,用于操作包含ASCII字符的文件。JAVA也支持其他的字符如Unicode,為了讀取包含Unicode字符的文件,JAVA語言設計者在JDK1.1中引入了字符流。ASCII作為Unicode的子集,對于英語字符的文件,可以可以使用字節流也可以使用字符流。

    3.Java中流類的超類主要由那些?

    - java.io.InputStream- java.io.OutputStream- java.io.Reader- java.io.Writer

    4. FileInputStream和FileOutputStream是什么?

    這是在拷貝文件操作的時候,經常用到的兩個類。在處理小文件的時候,它們性能表現還不錯,在大文件的時候,最好使用BufferedInputStream (或 BufferedReader) 和 BufferedOutputStream (或 BufferedWriter)

    5. 字節流和字符流,你更喜歡使用拿一個?
    個人來說,更喜歡使用字符流,因為他們更新一些。許多在字符流中存在的特性,字節流中不存在。比如使用BufferedReader而不是BufferedInputStreams或DataInputStream,使用newLine()方法來讀取下一行,但是在字節流中我們需要做額外的操作。

    6.System.out.println()是什么?
    println是PrintStream的一個方法。out是一個靜態PrintStream類型的成員變量,System是一個java.lang包中的類,用于和底層的操作系統進行交互。

    7.什么是Filter流?
    Filter Stream是一種IO流主要作用是用來對存在的流增加一些額外的功能,像給目標文件增加源文件中不存在的行數,或者增加拷貝的性能。

    8. 有哪些可用的Filter流?
    在java.io包中主要由4個可用的filter Stream。兩個字節filter stream,兩個字符filter stream. 分別是FilterInputStream, FilterOutputStream, FilterReader and FilterWriter.這些類是抽象類,不能被實例化的。

    有些Filter流的子類:
    - LineNumberInputStream 給目標文件增加行號
    - DataInputStream 有些特殊的方法如readInt(), readDouble()和readLine() 等可以讀取一個 int, double和一個string一次性的,
    - BufferedInputStream 增加性能
    - PushbackInputStream 推送要求的字節到系統中

    9.SequenceInputStream的作用?
    這個類的作用是將多個輸入流合并成一個輸入流,通過SequenceInputStream類包裝后形成新的一個總的輸入流。在拷貝多個文件到一個目標文件的時候是非常有用的。可用使用很少的代碼實現

    10.說說PrintStream和PrintWriter
    他們兩個的功能相同,但是屬于不同的分類。字節流和字符流。他們都有println()方法。

    11. 在文件拷貝的時候,那一種流可用提升更多的性能?
    在字節流的時候,使用BufferedInputStream和BufferedOutputStream。
    在字符流的時候,使用BufferedReader 和 BufferedWriter

    12 .說說管道流(Piped Stream)
    有四種管道流, PipedInputStream, PipedOutputStream, PipedReader 和 PipedWriter.在多個線程或進程中傳遞數據的時候管道流非常有用。

    13.說說File類
    它不屬于 IO流,也不是用于文件操作的,它主要用于知道一個文件的屬性,讀寫權限,大小等信息。注意:Java7中文件IO發生了很大的變化,專門引入了很多新的類來取代原來的基于java.io.File的文件IO操作方式。

    14. 說說RandomAccessFile?

    它在java.io包中是一個特殊的類,既不是輸入流也不是輸出流,它兩者都可以做到。他是Object的直接子類。通常來說,一個流只有一個功能,要么讀,要么寫。但是RandomAccessFile既可以讀文件,也可以寫文件。 DataInputStream 和 DataOutStream有的方法,在RandomAccessFile中都存在。

    參考資料(同致謝!)

    java IO體系的學習總結

    Java IO,硬骨頭也能變軟

    Java IO常見面試題

    Java 緩沖流簡介及簡單用法

    java 對象流的簡單使用

    jdk api_1.8中文參考

    總結

    以上是生活随笔為你收集整理的【图解Java】这下可以真的弄懂Java IO了~的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。