《java世界觀》文集說明
- 本文集記載的所有內容均是java的學習筆記总放,主要重點記錄概念店溢,可能不會為每個概念列舉完整的代碼例子俯画,代碼例子請移步《java種田記》文集
- 本文主要涉及內容來自開課吧新職課-JavaEE開發(fā)工程師V2.0
- 若有錯漏之處溉卓,歡迎各位指正
本文涉及類
File, InputStream, OutputStream, Reader, Writer, FileInputStream, FileOutputStream, FileWriter, InputStreamReader, OutputStreamWriter, PrintStream, PrintWriter, BufferedReader, Properties
正文
IO流概述
- 首先讓我們明確一點铜异,計算機中的任何數(shù)據(jù)(文本趾盐,圖片庶喜,視頻,音樂等)都是以二進制的形式救鲤,字節(jié)Byte作為單位進行存儲的久窟,所以數(shù)據(jù)傳輸時,底層均是二進制本缠,大多以位Bit作為單位
- 將數(shù)據(jù)傳輸?shù)牟僮饕暈橐环N數(shù)據(jù)的流動
- 可以按照傳輸?shù)姆较驅⒘鲃臃譃?輸入Input 和 輸出Output斥扛,合起來即IO,如果將一個文件從C盤傳輸?shù)紻盤丹锹,則對于C盤來說稀颁,在輸出,對于D盤來說楣黍,在輸入匾灶。
流的分類
- 如剛才所說,可以按照方向將流分為 輸入流 和 輸出流
- 按照流動的數(shù)據(jù)類型將流動分為 字節(jié)流 和 字符流锡凝,字符的本質也是字節(jié)粘昨,由于字符讀寫操作的需求將其劃分出來
Java.io常用類
Java中根據(jù)上文中的兩種分類,提供了4個頂級抽象父類窜锯,分別是 字節(jié)輸入流 InputStream, 字節(jié)輸出流 OutputStream, 字符輸入流 Reader, 和 字符輸出流 Writer张肾。無論是什么流,使用完畢后請務必調用close()釋放資源
文件操作
文件傳輸(讀寫)是常見的IO流涉及領域锚扎。要對文件進行操作就不得不提到路徑吞瞪。
路徑
路徑分為
- 絕對路徑
從盤符開始,是一個完整的路徑驾孔,無論當前在什么地方(路徑)芍秆,都指向那一個文件惯疙,如C:\\a.txt
(Windows),~/Downloads/a.txt
(Mac/UNIX) - 相對路徑
一個不完整的便捷路徑妖啥,在命令行/終端中則是當前路徑霉颠,在java項目中則是項目路徑,如a.txt
基礎操作
java為文件操作提供了 文件類 java.io.FIle 荆虱,一個File既可以表示文件也可以表示文件夾蒿偎,F(xiàn)ile類中提供靜態(tài)常量 默認名稱分隔符 separator,和 路徑分隔符 pathSeparator怀读,在進行路徑描述時應使用這些常量以兼容不同的操作系統(tǒng)诉位。
文件的常用操作為創(chuàng)建createNewFile()
和刪除delete()
,文件夾的常用操作為創(chuàng)建目錄mkdir()
或mkdirs()
菜枷,列舉目錄中的子文件/文件夾list()
或listFiles()
苍糠,刪除delete()
;還有一些常見的判斷操作啤誊,如岳瞭,isFile()
,isDirectory()
坷衍,exists()
寝优;常見屬性獲取,如枫耳,getPath()
乏矾,文件大小(單位字節(jié)Byte)length()
迁杨;更多操作或細節(jié)詳見API钻心。
讀寫操作
文件字節(jié)流
回到IO流的主題上來,用File類只能進行文件的創(chuàng)建和刪除铅协,若要進行讀寫操作則必須使用流捷沸,java為文件的字節(jié)讀寫提供了FileOutputStream 和 FileInputStream 類
兩者的構造函數(shù)中一參傳入文件對象(File類對象)或路徑字符串,二參傳入是否在已有文件內容基礎上進行添加的布爾值狐史,不傳默認是false痒给;前者的常用操作為write(byte[] b)
和write(byte[] b, int off, int len)
,后者的常用操作為read()
和read?(byte[] b)
骏全,此函數(shù)會返回讀入緩沖區(qū)的總字節(jié)數(shù)(存在有效讀取字節(jié)數(shù)小于緩沖區(qū)長度的情況)苍柏,兩個read()函數(shù)返回-1則意味著文件到達末尾,讀取完畢姜贡。
加密和解密
可以利用 FileInputStream 對文件的每一個字節(jié)進行讀取试吁,經(jīng)過一定的運算后,通過 FileOutputStream 將更改過的字節(jié)寫入新的文件進行加密楼咳。同理熄捍,通過反向運算可以解密烛恤。
對相同的數(shù)字進行二進制操作異或(^)兩次,得到的結果和最初輸入相同余耽,可以利用這一點進行加密編程缚柏,運行一次為加密,運行兩次為解密宾添;異或原理如下船惨,
- 1 ^ 1 = 0, 0 ^ 1 = 1;
- 1 ^ 0 = 1, 1 ^ 0 = 1;
- 0 ^ 1 = 1, 1 ^ 1 = 0;
- 0 ^ 0 = 0, 0 ^ 0 = 0.
文件字符流
字符編碼
如上文所說柜裸,計算機中以二進制存儲數(shù)據(jù)缕陕,字符編碼則是將二進制表示為字符的規(guī)則(“辭典”)
廣為人知的ASCII碼,就將常見英文符號疙挺,字母扛邑,阿拉伯數(shù)字與二進制進行了對應,如A是1000001 (65)铐然,ASCII碼中每個字符只用一個字節(jié)表示蔬崩,從00000000到11111111,最多可以表示256個不同的字符
256個字符可以將英文常用字符表示完畢搀暑,對于其他語種便可能不夠用沥阳,為了讓計算機顯示出其他語種的字符,各國均有發(fā)明更多的字符編碼自点,均兼容了ASCII碼桐罕,中國常用的字符編碼便有GBK,GB2312桂敛,GB18030功炮;當然,字符編碼能表示的字符越多术唬,每描述一個字符需要占用的空間則越大
亂碼薪伏,是由于輸入和輸出所使用的編碼不同,導致最終顯示無意義字符的一種現(xiàn)象〈植郑現(xiàn)如今跨國業(yè)務需求日益增加嫁怀,需求能夠兼容大部分國家語種的字符編碼,UTF-8應運而生借浊,它支持絕大部分語言塘淑,表示字符的字節(jié)長度不固定(動態(tài)),此字符編碼現(xiàn)被廣泛使用巴碗,故建議使用
字符流
如上文所提及朴爬,UTF-8中一個字符所占用的字節(jié)長度是不確定的,如果用字節(jié)流進行字符操作橡淆,往往會遇到讀取了“半個字”的情況召噩,導致后續(xù)操作出現(xiàn)問題母赵,最終結果無法解析。字符流通過對字節(jié)進行封裝具滴,將讀寫單位由字節(jié)轉換為字符凹嘲,解決了這個問題。
FileWriter 是java提供的文件字符輸出流构韵,除了Writer的常用操作外周蹭,還提供了append()函數(shù),例如fw.append(“鋤禾日當午”).append(“疲恢,”).append(“汗滴禾下土”);
緩沖 和 輸出流的flush()函數(shù)
為了提高效率凶朗,字節(jié)并不是馬上輸出的,往往緩沖了一定字節(jié)大小的內容才會統(tǒng)一輸出显拳;而當輸出的內容不足以填滿緩沖區(qū)棚愤,卻希望馬上可以輸出的時候,則需要調用 OutputStream 和 Writer 里的flush()函數(shù)杂数。而close()函數(shù)在關閉流之前也會調用flush()清空緩沖區(qū)并輸出內容宛畦。
轉換流
在網(wǎng)絡編程中,獲取的流往往是字節(jié)流揍移,需要轉換為字節(jié)流次和;而利用裝飾者模式,將字節(jié)流裝飾為字符流的轉換流是解決方案之一那伐。
打印流
打印流提供了各種各樣的print方法踏施,使用打印流可以用println(),format()等方法進行更便捷的字符操作
緩存讀取流
BufferedReader喧锦,提供一次讀取一行的readLine()操作
配置文件 Properties
java中的配置類 Properties 實際為鍵值對存儲(Map)读规,通過store()
將配置輸出到 .properties 文件中存儲,再通過load()
將文件中的信息讀取存儲到Properties對象中燃少,通過getProperty()
從對象中提取鍵對應的值字符串束亏,可以實現(xiàn)存儲處理應用配置的需求
Try-with-resources
如上文所說,所有的流在使用后都需要調用close()釋放資源阵具,而當我們使用try-catch處理異常時碍遍,語法上會非常麻煩;jdk1.7之后對此提供了支持阳液,允許在try后添加小括號創(chuàng)建實現(xiàn)closeable接口的資源怕敬,在使用完畢后會自動釋放;jdk1.9對此進行了優(yōu)化帘皿,在小括號內可以傳入多個先前創(chuàng)建過的closeable對象(多個對象之間用;隔開)东跪,在使用完畢后會自動釋放資源。