#day12-IO(字符流、Properties)
***
##1. 字符流引入
1. 使用字節流讀寫字符數據產生的問題
1. 問題1 : 若是寫出的是字符數據, 須要將字符數據轉換成字節數組.
2. 問題2 : 若是使用字節流讀取中文數據, 發生了 `亂碼`. 4
2. 集成電路
1. Cpu、內存、硬盤、IO輸入輸出硬件設備,都是屬於集成電路
2. 電子元件 : 只有兩種狀態,要麼開要麼關(1和0)
3. 集成電路就是無數個電子元件組合起來的
4. 例子
1. 01001001,8位 -》b -》 ASCII碼(1個字節,首位是0,只用7位,故表示128個)
2. encode(編碼): 漢語 -> 0101 編碼,以後方便計算機存儲
3. decode(解碼): 0101 -> 漢語 解碼,以後方便人類查看
4. messy code(亂碼) : 用一種A編碼表編碼,用B編碼表解碼java
3. 編碼表介紹
1. 字節轉成字符的規則
2. ascii碼錶,128個,佔一個字節:8位,首位是0,後7位表示 (1個字節)
3. ISO-8859-1(歐碼)256個,佔一個字節:8位全表示 (1個字節)
4. gbk 2個字節表示1個漢字(windows系統默認)
5. utf8 3個字節表示1個漢字(Java開發主流)
##2. 字符流體系
1. 便捷字符輸入流:FileReader
0. 需求:使用便捷字符輸入流解決了讀取中文亂碼的問題
1. 字符流 : 字節流 + 編碼表 (字節轉字符的規則)
2. FileReader 讀取字符文件的便捷類.
3. 特色 : 使用簡單,使用該類無需指定編碼表
4. 問題: 底層到底有沒有編碼表??? 有的和平臺默認使用編碼表一致,GBK
2. 便捷字符輸入流:FileWriter
0. 使用便捷字符輸出流寫入英文與中文到文件中
1. 寫出數據時, 字符串無需轉換.
2. 寫出時無需建立File對象, 也無需指定編碼表. 內部使用默認編碼表.程序員
3. 字符轉換輸出流:OutputStreamWriter
0. 需求 : 使用 GBK & UTF-8 寫出 hello,個人女神,I love you."
1. OutputStreamWriter(OutputStream out, String charsetName) 使用指定字符集
2. 是字符流通向字節流的橋樑 字符流 = 字節流 + 編碼表
3. 字符流的底層是調用字節流讀寫
4. 多種方式
0. FileWriter writer = new FileWriter(path);
1. new OutputStreamWriter(FileOutputStream fos);
2. OutputStreamWriter(OutputStream out, String charsetName)windows
4. 字符轉換輸入流:InputStreamReader
0. 使用InputStreamReader 讀取不一樣編碼的文件(GBK、UTF-8)
1. 多種方式
0. FileReader reader = new FileReader(path);
1. InputStreamReader(InputStream in) 建立一個使用默認字符集
2. InputStreamReader(InputStream in, String charsetName) 使用指定字符集數組
5. 編解碼和亂碼
1. 編碼 encode:將字符數據轉換成字節數據. 目的:將字符數據以字節的形式存儲到硬盤文件中.
2. 解碼 decode:將字節數據轉換成字符數據. 目的:將文件中的字節數據轉換爲字符給程序員查看.
3. 亂碼 messy code:以A編碼表進行編碼, 以B編碼表進行解碼, 結果就是亂碼. (編碼表和解碼錶對應不上就會產生亂碼)緩存
##3. 複製文件原理
1. 複製文件的方式
1. Reader & Writer 字符流複製文本文件 :
1. FileReader & FileWriter (使用環境默認編碼)
2. InputStreamReader & OutputStreamWriter (手動指定)
2. inputStream & 0utputStream
1. fileInputStream & fileOutputStream
2. 問題:既然字節流和字符流都能複製文件,那它們有何區別?網絡
3. 原理:
1. 字符流在複製過程當中須要先編碼後解碼,效率低。並且在複製圖片和音視頻文件時也由於編解碼的緣由,容易形成複製以後的文件產生問題。
2. 字節流複製過程沒有編解碼,效率高,並且不出錯
4. 總結
1. 文件複製應該用字節流
2. 字符流應該用來讀寫字符數據
## 4. 字符緩衝流
1. BufferedReader & BufferedWriter字符緩衝流
1. BufferedWriter : 接收 Writer.
1. FileWriter(GBK)-> 接收 String / File
2. OutputStreamWriter (UTF-8)-> 接收 OutputStream-> 傳遞FileOutputStream -> 接收 String / File
3. 緩衝流寫出三部曲
1. 寫出 2. 換行 3. 刷新
2. BufferedReader -> 接收 Reader
1. FileReader(GBK) -> 接收 String / File
2. InputStreamReade(UTF-8)-> 接收 InputStream -> 傳遞 FileInputStream -> 接收 String / File
## 5. 其它流
1. 打印流
1. PrintStream
1. printStream 無需手動關閉和刷新, 數據也能夠寫入到文件中 (自動刷新)
2. PrintStream 爲其餘輸出流添加了功能,使它們可以 `方便地打印各類數據值 print / println` 表示形式。數據結構
2. PrintWriter
1. PrintWriter 須要 `啓動自動刷新`.
2. 使用場景:網絡請求 -> request 請求 PrintWriter writer = request.getPrintWriter(); 做用: 向網頁中寫出數據.ui
2. 序列化和反序列化
0. 需求:將一個自定義對象存儲到文件中, 並讀取出來.
1. 概念
1. 序列化 :將數據結構或對象轉換成二進制串的過程
2. 反序列化 :二進制串轉換成數據結構或者對象的過程
2. ObjectOutputStream:將Java的對象寫入到文件中
1. 異常:NotSerializableException 不能序列化異常
2. 解決:類經過實現 java.io.Serializable 接口以啓用其序列化功能
3. Serializable接口
1. 當一個對象要能被序列化,這個對象所屬的類必須實現Serializable接口
2. 若是一個接口中沒有任何方法, 那麼該接口就被稱爲 `標識接口`
3. ObjectInputStream:將文件中的數據讀取爲 Java 對象.
1. 異常:InvalidClassException 非法類異常(修改該類)
2. 緣由以下:
1. 該類的序列版本號與從流中讀取的類描述符的版本號不匹配
2. 該類包含未知數據類型
3. 該類沒有可訪問的無參數構造方法
3. Serializable標記接口。該接口給須要序列化的類,提供了一個序列版本號serialVersionUID. 該版本號的目的在於驗證序列化的對象和對應類是否版本匹配。
4. 解決:在類中顯示聲明一個該對象的 UID 序列號
* 自動生成,根據該類全部數據計算
4. 瞬態關鍵字transient
1. 只要被transient修飾的屬性,在對象序列化時,這個屬性不會被序列化編碼
5. 練習和應用
1. 練習:集合(四大名著:做者) 進行序列化和反序列化
2. 應用:
1. 序列化這個概念太籠統,說白了就是方便計算機表述,使用010101的方式方便傳輸和存儲。
2. java 序列化 也是爲了 傳輸和存儲,只是 Serializable 是使用java內部序列化格式。開發中,因爲java自身的序列化信息不夠簡潔,通常不多有使用java 序列化對象進行通訊的。
##6. Properties類
1. Properties 類表示了一個持久的屬性集。Properties 可保存在流中或從流中加載。屬性列表中每一個鍵及其對應值都是一個字符串。
2. 特色:
1. Hashtable的子類,map集合中的方法均可以用。
2. 該集合沒有泛型。鍵值都是字符串。
3. 它是一個能夠持久化的屬性集。鍵值能夠存儲到集合中,也能夠存儲到持久化的設備(硬盤、U盤、光盤)上。鍵值的來源也能夠是持久化的設備。
4. 有和流技術相結合的方法。
3. 方法:
1. setProperty(String key, String value):調用 Hashtable 的方法 put
2. stringPropertyNames()返回此屬性列表中的鍵集
3. getProperty(String key)用指定的鍵在此屬性列表中搜索屬性
4. store(Writer,comments)和 store(OutputStream,comments)
1. 把集合中的數據,保存到指定的流所對應的文件中,參數comments表明對描述信息
5. load(InputStream) 和load(Reader)
1. 把指定流所對應的文件中的數據,讀取出來,保存到Propertie集合中code
4. 獲取本地系統的屬性集
1. Properties prop = System.getProperties() 全部屬性集
2. String country = System.getProperty("user.country") 單個屬性集
##8. Commons-IO 第三方開源包
1. Apache 軟件基金組織 : Commons-IO `通用 IO 包`
2. JAR包
1. (Java Archive,Java 歸檔文件)是與平臺無關的文件格式,它容許將許多文件組合成一個壓縮文件。
2. .jar 文件 : 集成了 class 文件. -> class 文件的壓縮包.
3. 導開源包的步驟
1. 在工程下建立一個lib文件夾(跟src平級)
2. 複製 .jar文件到lib目錄
3. 選中jar包 右單擊 -》 build path
4. FileUtils 類 :
1. static void copyFile(File srcFile, File destFile); 複製文件
2. static void copyDirectoryToDirectory(File srcDir, File destDir).複製文件夾
## 9. 流總結
1. "字節流 :"
1. InputStream : 字節輸入流
|-- FileInputStream
|-- BufferedInputStream 8k緩存 byte[]
2. OutputStream : 字節輸出流
|-- FileOutputStream
|-- BufferedOutputStream
2. "字符流 :"
1. Reader : 字符輸入流
|-- InputStreamReader : InputStream + 任意編碼表
|-- FileReader : InputStreamReader + 默認編碼表 (便捷類) 字節流 + 編碼表
|-- BufferedReader
2. Writer : 字符輸出流
|-- OutputStreamWriter : OutputStream + 任意編碼表
|-- FileWriter : OutputStreamWriter + 默認編碼表 (便捷類)字節流 + 編碼表
|-- BufferedWriter
3. "請問 : 如何選擇使用那種流呢?"
1. "問題1 : 讀取字節數據仍是字符數據?"
1. 字節 : BufferedInputStream / BufferedOutputStream
2. 字符 : BufferedReader / BufferedWriter
2. "問題2:複製文件用什麼流?"
1. 字節流:由於字符流須要編解碼,效率低,並且可能出錯。
3. "問題3 : 我是讀仍是寫?"
1. 讀 : BufferedInputStream / BufferedReader
2. 寫 : BufferedOutputStream / BufferedWriter
4. "問題4 : 是否須要高效緩衝呢 ?" 固然要.
1. 是 : 就用對應體系的緩衝流包起來. 緩衝流就是用來裝飾其它流的.因此,要加緩衝,就用緩衝流包裝其它流
5. "問題5 : 是否須要指定編碼表?"
1. 須要 , 轉換流. OutputStreamWriter & InputStreamReader
2. 不須要 , 便捷流. FileWriter & FileReader(默認編碼)
## 快捷鍵 1. 程序崩潰, windows -》ctrl + alt + delete -> 任務管理器 -》結束任務 2. 程序失去響應 -》 底部 ,右單機-》啓動任務管理器