day012 IO【轉換流、列印流、序列化】

MustangYL發表於2020-12-23

1 字元流

1.1 字元編碼表

編碼表就是位元組(數字)和字元(漢字或者其他語言)的對應關係表。

 

ASCII:                   1位元組(0 + 7個二進位制位)     128個字元

iso8859-1(latin)     1位元組                                       256個字元。

gb2312(1980)             1/2 個位元組                              包含了六千多中文或者符號。

big5                       1/2 個位元組                              支援繁體字。

gbk                       1/2 位元組                                  支援兩萬多的漢字以及字元。

unicode:國際標準碼錶。 可以表示任何國家的任何語言,並且任何字元都採用兩個位元組去儲存。 unicode8.0 甚至支援emoji。

 

UTF-8:萬國碼

 

UTF-32: 採用4個位元組去儲存。

UTF-16:採用2/3/4個位元組去儲存。

UTF-8: 採用1/2/3/4個位元組去儲存。

 

只需要知道兩個。

gbk: 中文在gbk中佔2個位元組。

utf-8: 中文在utf-8中佔3個

 

文字--->(數字) :編碼:就是看能看懂內容,轉換成看不懂的內容。

(數字)--->文字  : 解碼: 就是把看不懂的內容,轉換成看懂的內容。

 

1.2 io分類回顧

QQ截圖20201201100344.png

2 轉換流

2.1 轉換流寫入和讀取的工作流程

QQ截圖20201203084939.png

2.2 OutputStreamWriter

OutputStreamWriter 是轉換流。 是字元通向位元組的橋樑。

可以指定編碼集進行寫入。

構造方法:

OutputStreamWriter(OutputStream out): 需要傳遞一個位元組輸出流。   採用預設編碼方式進行寫入。

OutputStreamWriter(OutputStream out, String charsetName):  第一個引數為位元組輸出流,第二個引數為編碼集名稱。 可以指定編碼集進行寫入。

寫入方法。

寫入方法,和之前字元流的寫入方法是一樣的。因為OutputStreamWriter屬於字元流。

注意:

轉換流本身並不具備讀或者寫的功能,它的作用是查詢碼錶進行轉碼。

讀或者寫真正是由位元組流做的

 

指定的編碼集必須要存在,如果不存在就會報錯

ANSI 在windows指的就是gbk。

2.3 OutputStreamReader

InputStreamReader 也是轉換流。 位元組通向字元的橋樑。 

這個流可以指定編碼進行讀取。

 

構造方法:

InputStreamReader(InputStream in):傳遞一個位元組輸入流。 以預設編碼方式進行讀取。

InputStreamReader(InputStream in, String charsetName): 第一個是位元組輸入流。第二個是指定的編碼方式。可以指定編碼進行讀取。

讀取的方法:

通過轉換流讀取。 以字元為單位。 因為轉換流屬於字元流的一種。

注意:程式碼中是以字元為單位讀的。但是內部會使用InputStream位元組輸入流,以位元組為單位讀取。

注意:

轉換流本身並不具備讀或者寫的功能。它的作用查詢碼錶進行轉碼。

資料其實真正是由位元組流讀或者寫的。

 

檔案是使用哪種編碼儲存,那麼讀取的時候就要指定哪種編碼,否則就會出現亂碼。

轉換流作用:

可以指定編碼集進行讀寫。

2.4 InputStreamReader

InputStreamReader 也是轉換流。 位元組通向字元的橋樑。  

這個流可以指定編碼進行讀取。

 

構造方法

InputStreamReader(InputStream in):傳遞一個位元組輸入流。 以預設編碼方式進行讀取。

InputStreamReader(InputStream in, String charsetName): 第一個是位元組輸入流。第二個是指定的編碼方式。可以指定編碼進行讀取。

 

讀取的方法:

 通過轉換流讀取。 以字元為單位。 因為轉換流屬於字元流的一種。

 注意:程式碼中是以字元為單位讀的。但是內部會使用InputStream位元組輸入流,以位元組為單位讀取。

 

注意:

 轉換流本身並不具備讀或者寫的功能。它的作用查詢碼錶進行轉碼。

 資料其實真正是由位元組流讀或者寫的。

 

       檔案是使用哪種編碼儲存,那麼讀取的時候就要指定哪種編碼,否則就會出現亂碼。

 

 

轉換流作用:

 可以指定編碼集進行讀寫。

2.4 轉換流和子類的區別

字元流的繼承體系。

 

字元輸出流:

Writer: 是頂層父類。 是一個抽象類。

 |-- OutputStreamWriter: 轉換流,可以指定編碼方式進行寫入。

  |-- FileWriter: 是以預設的編碼方式進行寫入。 是父類的一個更簡單的用法。

   

字元輸入流:

Reader: 頂層父類,是一個抽象類。

 |-- InputStreamReader:轉換流,可以指定編碼進行讀取。

  |-- FileReader: 是以預設編碼進行讀取。 是父類更簡單的寫法。

   

總結:以下三種寫法是一樣的

 使用轉換流指定一個編碼方式,這個指定的編碼方式為gbk。

 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file03.txt"), "gbk");

 

 使用轉換流,不指定編碼方式,會採用的預設的gbk。

 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file03.txt"));

 

 使用子類FileWriter,採用的就是預設的gbk。

 FileWriter fw = new FileWriter("file03.txt");

3 序列化流

QQ拼音截圖未命名.png

3.1 ObjectOutputStream 序列化流

 

ObjectOutputStream 叫做序列化流,可以將java程式中的物件寫入到檔案中。

 

構造方法:

             ObjectOutputStream(OutputStream out): 傳遞一個位元組輸出流物件。

 

其他方法:

void writeObject(Object obj):向檔案中寫入一個物件。

 

要寫入的物件必須實現一個介面。這個介面叫做Serializable,如果沒有實現這個介面,就會引發NotSerializableException

 

寫入進去的內容我們是看不懂,因為它不是給我們看的。

 

3.2 ObjectInputStream 反序列化流

ObjectInputStream叫做反序列化流, 用來從檔案中讀取物件。

構造方法

 ObjectInputStream(InputStream in): 傳遞一個位元組輸入流

 

讀取物件的方法:

 Object readObject(): 讀取物件

 

注意:如果讀取物件的時候,這個物件的class檔案不存在,就會引發ClassNotFoundException。

 

如果想要寫入多個物件,可以把這些物件放入到一個集合中,然後把集合寫入到檔案,最終再讀取。

 

3.3 Serializable介面

Serializable 是序列化介面,一個類的物件想要被序列化,必須要實現這個介面。

這個介面中沒有任何方法,它的作用只是做一個標記,實現這個介面的類的物件才能夠被序列化。

 

3.4 注意

1. 被static修飾的成員,不會被序列化。

2. 如果希望某個物件的成員變數在序列化的時候不要寫入到檔案中,同時也不希望使用static。

          可以使用另外一個關鍵字,這個關鍵字叫做transient。

          transient 表示瞬態,被transient修飾的屬性不會被序列化。

3.5 版本號衝突問題及解決方法

QQ截圖20201222233207.png

 

 

如果向檔案中寫入一個物件後,對這個物件所在的類進行修改,然後再讀取就會引發異常。

原因是因為讀取前和讀取後的版本號(序列化)不一致

 

如何解決?

可以給這個類分配一個固定的版本號,這樣這個類無論怎麼修改,這個版本號都不會變。

 

如何給這個類分配一個固定的版本號?

直接在這個類中給出一個靜態常量,叫做serialVersionUID。 這個靜態常量表示的就是版本號(序列化)的意思

 

4 列印流

特點:

 1. 只有輸出,沒有輸入(只能寫,不能讀)

 2. 使用比較方便。

 

PrintWriter(字元列印流):

 構造方法:

  PrintWriter(File file)  

  PrintWriter(OutputStream out)

  PrintWriter(String fileName)  

  PrintWriter(Writer out)

PrintStream(位元組列印流):

 構造方法:

  PrintStream(File file)

  PrintStream(OutputStream out)

  PrintStream(String fileName)  

   

列印流裡面寫入的方法。

 write: 如果寫入的是數字,會查詢ASCII碼最終寫入這個數字對應的字元。

 print: 如果寫入的是數字,會原樣寫入到檔案中。寫入之後不會換行。

 println:寫入之後會自動換行。

 

使用步驟:

 1. 建立列印流物件

 2. 呼叫方法,進行寫入。

 3. 釋放資源

 

列印流的自動重新整理

字元輸出流寫資料的時候需要重新整理。

位元組流寫的時候不需要重新整理

 

自動重新整理的要求

1. 輸出目標必須是流;

 PrintWriter(OutputStream out, boolean autoFlush)

 PrintWriter(Writer out, boolean autoFlush)

2. 第二的構造引數指定為true;

3. 必須呼叫println、printf或format之一才會生效。

 

5 Commons-IO 等第三方工具的使用

什麼是第三方?

 第一方: Oracle官方。

 第二方: 程式設計師自己。

 第三方: 除此之外全部都是第三方。

 

後期用的東西大多都是由第三方提供的工具。

這些工具都會以jar包的形式給你。

jar包就是一種壓縮包。裡面放的都是.class檔案。

 

現在我們學的這個工具叫做commons-io,他也是第三方工具,也是也jar包的形式提供的,它對應的jar包是 commons-io-2.6.jar

 

commons-io 是由Apache(阿帕奇)提供的一個第三方工具,作用是簡化了我們對IO流的操作。

Apache是 美國開源基金組織。

後期很多框架或者其他工具都是由apache維護或者提供的。

比如: tomcat。 active-mq。 struts2。 haddop,commons-io

 

 

 

如果要使用第三方工具,必須要進行導jar包。(重要)

步驟:

 1. 在當前專案下新建資料夾,叫做lib

 2. 把要匯入的jar包拷貝到這個lib資料夾下。  

 3. 點選jar包 -> 右鍵 -> build path -> add to build path

 

在commons-io中,有一個工具類,可以完成很多功能,這個類叫做FileUtils

裡面的方法

static void writeStringToFile(File file, String data):向檔案中寫入字串。

static String readFileToString(File file):讀取檔案,並返回字串。

static void copyFile(File srcFile, File destFile): 複製檔案。srcFile原始檔。destFile目標檔案

static void copyDirectoryToDirectory(File srcDir, File destDir): 複製資料夾。

 

@Deprecated //這個東西叫做註解,這個註解的作用表示這個東西已經過時了,被用這個註解的方法,使用時方法就會被劃上橫線。

 

5.1 關聯原始碼

    按住Ctrl點方法,然後點Attach Source...,然後點External location,然後如果原始碼是以檔案形式提供的就選External File,如果原始碼是以資料夾形式提供的,就選External Folder。

 

5 NIO介紹

BIO:同步阻塞IO

NIO:同步非阻塞IO。netty,dubbo

在指定IO操作的時候,可以去做其他事情。

NIO是基於 緩衝區, 通道,選擇器。

AIO:非同步非阻塞IO

 

阻塞指的是執行緒阻塞,執行緒在阻塞的時候就不能幹其他事情了。

阻塞:看成去銀行排隊取錢,一直ATM前面排隊。

非阻塞:去櫃檯拿個號,然後等著取錢,等著的時候,可以幹別的。

 

相關文章