1. 程式人生 > >Java中的IO流 - 入門篇

Java中的IO流 - 入門篇

前言

大家好啊,我是湯圓,今天給大家帶來的是《Java中的IO流-入門篇》,希望對大家有幫助,謝謝

 

由於Java的IO類有很多,這就導致我剛開始學的時候,感覺很亂,每次用到都是上網搜,結果每次用完就忘;

後來沉下心去看書學習,才明白都是有規律的;

這裡先做個簡單的介紹,作為入門級教程,後面還有很多要學習的,有空再整理吧。

簡介

檔案IO流,主要有兩種方式

  1. 位元組流:基於普通的Java物件,僅適用於Java程式之間的讀寫

  2. 字元流:基於普通的文字字串,不僅適用於Java程式之間的讀寫,也適用於Java程式和其他語言程式之間的讀寫

本例中用到的相關類如下:

所有的讀寫操作都是針對記憶體而言的,因為程式就是執行在記憶體中

讀操作就是從磁碟檔案或網路流讀到記憶體,對於記憶體而言就是Input

寫操作就是從記憶體寫到磁碟檔案或網路流,對於記憶體而言就是Output

 

下面分別介紹這兩種方式

位元組流:基於普通的Java物件

位元組流的讀和寫都是基於Java程式而言,比如在一個機器上的Java程式寫入一個物件到檔案,然後傳輸到另一個機器上的Java程式去讀取檔案中的物件

寫入Java物件時,會先將Java物件序列化(物件轉為位元組),然後寫入

讀取Java物件時,會先將Java物件反序列化(位元組轉為物件),然後讀取

寫物件

將物件寫入到檔案中,需要先把物件序列化,然後再把序列化後的位元組寫入到檔案中;

序列化就是將物件的屬性資訊轉為一系列位元組(不包括transient 型別的屬性,下面會介紹)

大概流程如下所示:

讀物件

將物件從檔案中讀出來,需要先反序列化,然後再轉為對應的Java物件,並恢復物件屬性值

反序列化就是將一系列位元組轉為真實的物件例項(不包括transient型別的屬性)

大概流程如下所示:

transient

該修飾符 字面意思是瞬時的,短暫的

用在物件的屬性上,就表示這個屬性是暫時有效的,等序列化的時候會失效

在反序列化的時候,這個屬性就會為null(如果屬性是物件引用)或基礎型別的預設值(如果屬性是基礎型別)

比如密碼等比較隱私的屬性,我們就可以設定為transient

,這樣就不會在傳輸過程中被被人攔截,從而破解出密碼

 

程式碼


public class ObjectIoDemo {

   public static void main(String[] args) throws IOException, ClassNotFoundException {
       InnerObject object1 = new InnerObject(10);
       String filename = "object.bin";
       writeObjectFun(filename, object1);
       InnerObject objectReturn = (InnerObject) readObjectFun(filename);
       System.out.println(objectReturn);

  }

   // 寫物件 到指定檔案
   public static void writeObjectFun(String filename, Object o) throws IOException {
       FileOutputStream fileOutputStream = new FileOutputStream(filename);
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
       objectOutputStream.writeObject(o);
       // 關閉流,fileOutputStream會一併關閉
       objectOutputStream.close();
  }

   // 讀物件 從指定檔案
   public static Object readObjectFun(String filename) throws IOException, ClassNotFoundException {
       FileInputStream fileInputStream = new FileInputStream(filename);
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
       Object o = objectInputStream.readObject();
       // 關閉流,fileInputStream會一併關閉
       objectInputStream.close();
       return o;
  }
}
class InnerObject implements Serializable{

   @Override
   public String toString() {
       return "InnerObject{" +
               "num=" + num +
               '}';
  }

   public InnerObject(int num) {
       this.num = num;
  }

   public int getNum() {
       return num;
  }

   public void setNum(int num) {
       this.num = num;
  }

   private int num;
}

 

如果要寫入的Java物件沒有序列化,則會報錯如下

Exception in thread "main" java.io.NotSerializableException: com.jalon.basic.io.InnerObject
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.jalon.basic.io.ObjectIoDemo.writeObjectFun(ObjectIoDemo.java:28)
at com.jalon.basic.io.ObjectIoDemo.main(ObjectIoDemo.java:19)

 

字元流:基於普通文字字串

字元流寫入到檔案中的資料,是作為通用文字資料來處理的,這樣Java程式和其他程式都可以去讀寫這個檔案

寫文字

大致流程如下:

讀文字

大致流程如下:

BufferedReader和BufferedWriter的作用

為什麼要用緩衝區呢?直接用FileReader和FileWriter不也可以嗎?

如果直接用FileWriterFileReader是可以執行,只不過效率會比較低,因為每一次的讀寫都是針對磁碟操作的;

BufferedWriterBufferedReader這兩個緩衝區可以減少磁碟的讀寫次數;

BufferedReader:程式可以從磁碟一次性讀很多資料到緩衝區,再從緩衝區一次次讀,等緩衝區為空時再去磁碟讀;

BufferedWriter:程式可以寫多次到緩衝區,等快取區滿了再一次性寫入到磁碟中

程式碼


public class TextIoDemo {
   public static void main(String[] args) throws IOException {
       String filename = "string.txt";
       writeString(filename, "hello world");
       String res = readString(filename);
       System.out.println(res);
  }
// 寫字串到指定檔案
   public static void writeString(String filename, String content) throws IOException {
       FileWriter fileWriter = new FileWriter(filename);
       BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
       bufferedWriter.write(content);

       bufferedWriter.close();
  }
// 從指定檔案讀取字串
   public static String readString(String filename) throws IOException {
       FileReader fileReader = new FileReader(filename);
       BufferedReader bufferedReader = new BufferedReader(fileReader);
       String line = "";
       StringBuilder stringBuilder = new StringBuilder();
       while ((line=bufferedReader.readLine())!=null){
           stringBuilder.append(line);
      }
       bufferedReader.close();
       return stringBuilder.toString();
  }
}

總結

IO流分為位元組流和字元流

如果讀寫兩邊都是Java程式,則推薦用位元組流,序列化和反序列化很方便

如果一邊是Java程式,另一邊是其他語言的程式,則推薦用字元流,讀寫的內容都是文字格式,方便解析

上面只是列出了個別讀寫類,Java中讀寫類還有很多,大家感興趣的可以去java.io下檢視

參考

  1. 《Head First Java》(第二版)

  2. 《Java 核心技術卷一》(第十版)

  3. 《Java 程式設計思想》(第四版)

後記

最後,感謝大家的觀看,