亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言
io流用到的地方很多,就比如上傳下載,傳輸,設計模式等....基礎打扎實了,才能玩更高端的。

在博主認為真正懂IO流的優秀程序員每次在使用IO流之前都會明確分析如下四點:

(1)明確要操作的數據是數據源還是數據目的(也就是要讀還是要寫)
(2)明確要操作的設備上的數據是字節還是文本
(3)明確數據所在的具體設備
(4)明確是否需要額外功能(比如是否需要轉換流、高效流等)

以上四點將會在文章告白IO流的四點明確里面小結一下,如果各位真能熟練以上四點,我覺得這篇文章你就沒必要看了,因為你已經把IO玩弄與股掌之中,萬物皆可被你盤也就也不再話下了。

@

1、告白IO流的四點明確

(1)明確要操作的數據是數據源還是數據目的(要讀還是要寫)

源:
InputStream Reader

目的:
OutputStream Writer

(2)明確要操作的設備上的數據是字節還是文本

源:

字節: InputStream

文本: Reader

目的:

字節: OutputStream

文本: Writer

(3)明確數據所在的具體設備

源設備:

硬盤:文件 File開頭

內存:數組,字符串

鍵盤:System.in

網絡:Socket

對應目的設備:

硬盤:文件 File開頭

內存:數組,字符串

屏幕:System.out

網絡:Socket

(4)明確是否需要額外功能

需要轉換—— 轉換流 InputStreamReader 、OutputStreamWriter

需要高效—— 緩沖流Bufferedxxx

多個源—— 序列流 SequenceInputStream

對象序列化—— ObjectInputStream、ObjectOutputStream

保證數據的輸出形式—— 打印流PrintStream 、Printwriter

操作基本數據,保證字節原樣性——DataOutputStream、DataInputStream

到這里,我們再來看看IO流的分類吧
 

史上最騷最全最詳細的IO流教程,沒有之一

 


OK,準備好了告白IO流了咩?

2、File類

至于IO流,也就是輸入輸出流,從文件出發到文件結束,至始至終都離不開文件,所以IO流還得從文件File類講起。

1.1 File概述

JAVA.io.File 類是專門對文件進行操作的類,只能對文件本身進行操作,不能對文件內容進行操作。
java.io.File 類是文件和目錄路徑名的抽象表示,主要用于文件和目錄的創建、查找和刪除等操作。

怎么理解上面兩句話?其實很簡單!

第一句就是說File跟流無關,File類不能對文件進行讀和寫也就是輸入和輸出!
第二句就是說File主要表示類似D:\文件目錄1與D:\文件目錄1\文件.txt,前者是文件夾(Directory)后者則是文件(file),而File類就是操作這兩者的類。

1.2 構造方法

在java中,一切皆是對象,File類也不例外,不論是哪個對象都應該從該對象的構造說起,所以博主來分析分析File類的構造方法。首先從API開始著手
 

史上最騷最全最詳細的IO流教程,沒有之一

 


我們主要來學習一下比較常用的三個:

1、 public File(String pathname) :通過將給定的路徑名字符串轉換為抽象路徑名來創建新的 File實例。
2、 public File(String parent, String child) :從父路徑名字符串和子路徑名字符串創建新的 File實例。
3、 public File(File parent, String child) :從父抽象路徑名和子路徑名字符串創建新的 File實例。

看字描述不夠生動不夠形象不得勁?沒得事,下面進行構造舉例,馬上就生動形象了,代碼如下:

File類的注意點:

一個File對象代表硬盤中實際存在的一個文件或者目錄。File類構造方法不會給你檢驗這個文件或文件夾是否真實存在,因此無論該路徑下是否存在文件或者目錄,都不影響File對象的創建。

1.3 常用方法

File的常用方法主要分為獲取功能、獲取絕對路徑和相對路徑、判斷功能、創建刪除功能的方法

1.3.1 獲取功能的方法

1、public String getAbsolutePath() :返回此File的絕對路徑名字符串。

2、public String getPath() :將此File轉換為路徑名字符串。

3、public String getName() :返回由此File表示的文件或目錄的名稱。

4、public long length() :返回由此File表示的文件的長度。

以上方法測試,代碼如下【注意測試以自己的電腦文件夾為準】:

注意:length(),表示文件的長度。但是File對象表示目錄,則返回值未指定。

1.3.2 絕對路徑和相對路徑

絕對路徑:一個完整的路徑,以盤符開頭,例如F://aaa.txt。
相對路徑:一個簡化的路徑,不以盤符開頭,例如//aaa.txt//b.txt。

1、路徑是不區分大小寫
2、路徑中的文件名稱分隔符windows使用反斜杠,反斜杠是轉義字符,兩個反斜杠代表一個普通的反斜杠

1.3.3判斷功能的方法

1、 public boolean exists() :此File表示的文件或目錄是否實際存在。
2、 public boolean isDirectory() :此File表示的是否為目錄。
3、public boolean isFile() :此File表示的是否為文件。

方法演示,代碼如下:

1.3.4 創建刪除功能的方法

  • public boolean createNewFile() :文件不存在,創建一個新的空文件并返回true,文件存在,不創建文件并返回false。
  • public boolean delete() :刪除由此File表示的文件或目錄。
  • public boolean mkdir() :創建由此File表示的目錄。
  • public boolean mkdirs() :創建由此File表示的目錄,包括任何必需但不存在的父目錄。

其中,mkdirs()和mkdir()方法類似,但mkdir(),只能創建一級目錄,mkdirs()可以創建多級目錄比如//a//b//c,所以開發中一般用mkdirs();

這些方法中值得注意的是createNewFile方法以及mkdirmkdirs的區別

方法測試,代碼如下:

注意:delete方法,如果此File表示目錄,則目錄必須為空才能刪除。

1.4 目錄的遍歷

  • public String[] list() :返回一個String數組,表示該File目錄中的所有子文件或目錄。
  • public File[] listFiles() :返回一個File數組,表示該File目錄中的所有的子文件或目錄。
史上最騷最全最詳細的IO流教程,沒有之一

 


listFiles在獲取指定目錄下的文件或者文件夾時必須滿足下面兩個條件

1,指定的目錄必須存在

2,指定的必須是目錄。否則容易引發返回數組為null,出現NullPointerException異常

1.5 遞歸遍歷文件夾下所有文件以及子文件

不說啥了,直接上代碼:

如果對上面的代碼有疑問,可以隨時聯系我,博主一直都在!

3、初探IO流

1.1 什么是IO

我想在座各位肯定經歷都過這樣的場景。當你編輯一個文本文件也好用eclipse打代碼也罷,忘記了ctrl+s ,在你關閉文件的哪一瞬間手殘點了個不該點的按鈕,但你反應過來,心早已拔涼拔涼的了。

我們把這種數據的傳輸,可以看做是一種數據的流動,按照流動的方向,以內存為基準,分為輸入input 和輸出output ,即流向內存是輸入流,流出內存的輸出流。

Java中I/O操作主要是指使用java.io包下的內容,進行輸入、輸出操作。輸入也叫做讀取數據,輸出也叫做作寫出數據

1.2 IO的分類

根據數據的流向分為:輸入流 和 輸出流

  • 輸入流 :把數據從其他設備上讀取到內存中的流。
  • 輸出流 :把數據從內存 中寫出到其他設備上的流。

根據數據的類型分為:字節流 和 字符流

  • 字節流 :以字節為單位,讀寫數據的流。
  • 字符流 :以字符為單位,讀寫數據的流。

分類之后對應的超類(V8提示:超類也就是父類的意思)
| | 輸入流 | 輸出流
|--|--|--|
| 字節流 | 字節輸入流 InputStream |字節輸出流 OutputStream |
| 字符流 | 字符輸入流 Reader|字符輸出流 Writer|

注:
由這四個類的子類名稱基本都是以其父類名作為子類名的后綴。
如:InputStream的子類FileInputStream。
如:Reader的子類FileReader。

 

史上最騷最全最詳細的IO流教程,沒有之一

 

1.3 關于IO的分流向說明

啥都不說了,看圖吧
 

史上最騷最全最詳細的IO流教程,沒有之一

 


史上最騷最全最詳細的IO流教程,沒有之一

 

字節流OutputStream與InputStream的故事

OutputStream與InputStream的繼承關系
 

史上最騷最全最詳細的IO流教程,沒有之一

 

2.1 文件的世界里一切皆為字節

我們必須明確一點的是,一切文件數據(文本、圖片、視頻等)在存儲時,都是以二進制數字的形式保存,都一個一個的字節,那么傳輸時一樣如此。所以,字節流可以傳輸任意文件數據。在操作流的時候,我們要時刻明確,無論使用什么樣的流對象,底層傳輸的始終為二進制數據。

2.2 字節輸出流(OutputStream)

java.io.OutputStream抽象類是表示字節輸出流的所有類的超類(父類),將指定的字節信息寫出到目的地。它定義了字節輸出流的基本共性功能方法,不要問我OutputStream為啥可以定義字節輸出流的基本共性功能方法,熊dei啊,上一句說過了OutputStream是字節輸出流的所有類的超類,繼承知識,懂?(如果是真的不理解的小白同學,可以點擊藍色字體繼承進入補習)

字節輸出流的基本共性功能方法:

1、 public void close() :關閉此輸出流并釋放與此流相關聯的任何系統資源。
2、 public void flush() :刷新此輸出流并強制任何緩沖的輸出字節被寫出。
3、 public void write(byte[] b):將 b.length個字節從指定的字節數組寫入此輸出流。
4、 public void write(byte[] b, int off, int len) :從指定的字節數組寫入 len字節,從偏移量 off開始輸出到此輸出流。 也就是說從off個字節數開始讀取一直到len個字節結束
5、 public abstract void write(int b) :將指定的字節輸出流。

以上五個方法則是字節輸出流都具有的方法,由父類OutputStream定義提供,子類都會共享以上方法

FileOutputStream類

OutputStream有很多子類,我們從最簡單的一個子類FileOutputStream開始。看名字就知道是文件輸出流,用于將數據寫出到文件。

FileOutputStream構造方法

不管學啥子,只有是對象,就從構造方法開始!

1、 public FileOutputStream(File file):根據File對象為參數創建對象。 
2、 public FileOutputStream(String name): 根據名稱字符串為參數創建對象。

推薦第二種構造方法【開發常用】:

就以上面這句代碼來講,類似這樣創建字節輸出流對象都做了三件事情
1、調用系統功能去創建文件【輸出流對象才會自動創建】
2、創建outputStream對象
3、把foutputStream對象指向這個文件

注意:
創建輸出流對象的時候,系統會自動去對應位置創建對應文件,而創建輸出流對象的時候,文件不存在則會報FileNotFoundException異常,也就是系統找不到指定的文件異常。

當你創建一個流對象時,必須直接或者間接傳入一個文件路徑。比如現在我們創建一個FileOutputStream流對象,在該路徑下,如果沒有這個文件,會創建該文件。如果有這個文件,會清空這個文件的數據。有興趣的童鞋可以測試一下,具體代碼如下:

FileOutputStream寫出字節數據

使用FileOutputStream寫出字節數據主要通過Write方法,而write方法分如下三種

  1. 寫出字節:write(int b) 方法,每次可以寫出一個字節數據,代碼如下:

雖然參數為int類型四個字節,但是只會保留一個字節的信息寫出。流操作完畢后,必須釋放系統資源,調用close方法,千萬記得。

  1. 寫出字節數組:write(byte[] b),每次可以寫出數組中的數據,代碼使用演示:
  1. 寫出指定長度字節數組:write(byte[] b, int off, int len) ,每次寫出從off索引開始,len個字節,代碼如下:

FileOutputStream實現數據追加續寫、換行

經過以上的代碼測試,每次程序運行,每次創建輸出流對象,都會清空目標文件中的數據。如何保留目標文件中數據,還能繼續追加新數據呢?并且實現換行呢?其實很簡單,這個時候我們又要再學習FileOutputStream的另外兩個構造方法了,如下:

1、public FileOutputStream(File file, boolean Append)

2、public FileOutputStream(String name, boolean append)

這兩個構造方法,第二個參數中都需要傳入一個boolean類型的值,true 表示追加數據,false 表示不追加也就是清空原有數據。這樣創建的輸出流對象,就可以指定是否追加續寫了,至于Windows換行則是 nr ,下面將會詳細講到。

實現數據追加續寫代碼如下:

Windows系統里,換行符號是rn ,具體代碼如下:

回車符r和換行符n :回車符:回到一行的開頭(return)。換行符:下一行(newline)。系統中的換行:Windows系統里,每行結尾是 回車+換行 ,即rn;Unix系統里,每行結尾只有 換行 ,即n;mac系統里,每行結尾是 回車 ,即r。從 Mac OS X開始與linux統一。

2.3 字節輸入流(InputStream)

java.io.InputStream抽象類是表示字節輸入流的所有類的超類(父類),可以讀取字節信息到內存中。它定義了字節輸入流的基本共性功能方法。

字節輸入流的基本共性功能方法:

1、 public void close() :關閉此輸入流并釋放與此流相關聯的任何系統資源。
2、public abstract int read(): 從輸入流讀取數據的下一個字節。

3、 public int read(byte[] b): 該方法返回的int值代表的是讀取了多少個字節,讀到幾個返回幾個,讀取不到返回-1

FileInputStream類

java.io.FileInputStream類是文件輸入流,從文件中讀取字節。

FileInputStream的構造方法

1、 FileInputStream(File file): 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的 File對象 file命名。
2、 FileInputStream(String name): 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的路徑名name命名。

同樣的,推薦使用第二種構造方法:

當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有該文件,會拋出FileNotFoundException 。

構造舉例,代碼如下:

FileInputStream讀取字節數據

  1. 讀取字節:read方法,每次可以讀取一個字節的數據,提升為int類型,讀取到文件末尾,返回-1,代碼測試如下【read.txt文件中內容為abcde】:

循環改進讀取方式,代碼使用演示:

  1. 使用字節數組讀取:read(byte[] b),每次讀取b的長度個字節到數組中,返回讀取到的有效字節個數,讀取到末尾時,返回-1 ,代碼使用演示:

由于read.txt文件中內容為abcde,而錯誤數據d,是由于最后一次讀取時,只讀取一個字節e,數組中,上次讀取的數據沒有被完全替換【注意是替換,看下圖】,所以要通過len ,獲取有效的字節
 

史上最騷最全最詳細的IO流教程,沒有之一

 


代碼如下:

在開發中一般強烈推薦使用數組讀取文件,代碼如下:

字節流FileInputstream復制圖片

復制圖片原理
 

史上最騷最全最詳細的IO流教程,沒有之一

 

代碼實現

復制圖片文件,代碼如下:

復制文本、圖片、mp3、視頻等的方式一樣

到這里,已經從File類講到了字節流OutputStream與InputStream,而現在將主要從字符流Reader和Writer的故事開展。

字符流Reader和Writer的故事

字符流Reader和Writer的故事從它們的繼承圖開始,啥都不說了,直接看圖
 

史上最騷最全最詳細的IO流教程,沒有之一

 

字符流

字符流的由來:因為數據編碼的不同,因而有了對字符進行高效操作的流對象,字符流本質其實就是基于字節流讀取時,去查了指定的碼表,而字節流直接讀取數據會有亂碼的問題(讀中文會亂碼),這個時候小白同學就看不懂了,沒事,咋們先來看個程序:

具體現狀分析
 

史上最騷最全最詳細的IO流教程,沒有之一

 


話說,就是你哥我敢摸si,那你哥我肯定也不認識這玩意啊: ??¥??¢????±

字節流讀取中文字符時,可能不會顯示完整的字符,那是因為一個中文字符占用多個字節存儲。

那字節流就沒辦法了嗎?不,字節流依舊有辦法,只是麻煩了點,代碼如下:

這是為啥呢?沒錯解碼的正是String,查看new String()的源碼,String構造方法有解碼功能,并且默認編碼是utf-8,代碼如下:

盡管字節流也能有辦法決絕亂碼問題,但是還是比較麻煩,于是java就有了字符流,字符為單位讀寫數據,字符流專門用于處理文本文件。如果處理純文本的數據優先考慮字符流,其他情況就只能用字節流了(圖片、視頻、等等只文本例外)。

從另一角度來說:字符流 = 字節流 + 編碼表

1、 字符輸入流(Reader)

java.io.Reader抽象類是字符輸入流的所有類的超類(父類),可以讀取字符信息到內存中。它定義了字符輸入流的基本共性功能方法。

字符輸入流的共性方法

1、public void close() :關閉此流并釋放與此流相關聯的任何系統資源。
2、 public int read(): 從輸入流讀取一個字符。
3、 public int read(char[] cbuf): 從輸入流中讀取一些字符,并將它們存儲到字符數組 cbuf中

FileReader類

java.io.FileReader類是讀取字符文件的便利類。構造時使用系統默認的字符編碼和默認字節緩沖區。

構造方法

1、FileReader(File file): 創建一個新的 FileReader ,給定要讀取的File對象
2、 FileReader(String fileName): 創建一個新的 FileReader ,給定要讀取的文件的字符串名稱

構造方法的使用就算不寫應該都很熟悉了吧,代碼如下:

FileReader讀取字符數據

  1. 讀取字符:read方法,每次可以讀取一個字符的數據,提升為int類型,讀取到文件末尾,返回-1,循環讀取,代碼使用演示:

至于讀取的寫法類似字節流的寫法,只是讀取單位不同罷了。

2、字符輸出流(Writer)

java.io.Writer抽象類是字符輸出流的所有類的超類(父類),將指定的字符信息寫出到目的地。它同樣定義了字符輸出流的基本共性功能方法。

字符輸出流的基本共性功能方法

1、void write(int c) 寫入單個字符。
2、void write(char[] cbuf)寫入字符數組。
3、 abstract void write(char[] cbuf, int off, int len)寫入字符數組的某一部分,off數組的開始索引,len寫的字符個數。
4、 void write(String str)寫入字符串。
5、void write(String str, int off, int len) 寫入字符串的某一部分,off字符串的開始索引,len寫的字符個數。
6、void flush()刷新該流的緩沖。
7、void close() 關閉此流,但要先刷新它。

FileWriter類

java.io.FileWriter類是寫出字符到文件的便利類。構造時使用系統默認的字符編碼和默認字節緩沖區。

構造方法

1、 FileWriter(File file): 創建一個新的 FileWriter,給定要讀取的File對象。
2、FileWriter(String fileName): 創建一個新的 FileWriter,給定要讀取的文件的名稱。

依舊是熟悉的構造舉例,代碼如下:

FileWriter寫出數據

寫出字符:write(int b) 方法,每次可以寫出一個字符數據,代碼使用演示:

【注意】關閉資源時,與FileOutputStream不同。 如果不關閉,數據只是保存到緩沖區,并未保存到文件。

關閉close和刷新flush

因為內置緩沖區的原因,如果不關閉輸出流,無法寫出字符到文件中。但是關閉的流對象,是無法繼續寫出數據的。如果我們既想寫出數據,又想繼續使用流,就需要flush 方法了。

flush :刷新緩沖區,流對象可以繼續使用。
close:先刷新緩沖區,然后通知系統釋放資源。流對象不可以再被使用了。

flush還是比較有趣的,童鞋們不自己運行一下還真不好體會,現在博主就寫個程序讓你體會體會:
字符流

史上最騷最全最詳細的IO流教程,沒有之一

 


運行效果是怎么樣的呢?答案是b.txt文件中依舊是空的,是的并沒有任何東西,為啥呢?熊dei啊,我在上面就用紅色字體特別標注過了,就是這句話: 【注意】關閉資源時,與FileOutputStream不同。 如果不關閉,數據只是保存到緩沖區,并未保存到文件。這個時候反應過來了吧,可見實踐例子的重要性,編程就是這樣,不去敲,永遠學不會!!!所以一定要去敲,博主沒敲過10萬行代碼真的沒有臉出去說自己是學java的。所以,大家一定要多思考,多敲啊!!!

所以,我們在以上的代碼中再添加下面三句代碼,就完美了,b.txt文件就能復制到源文件的數據了!

flush()這個函數是清空的意思,用于清空緩沖區的數據流,進行流的操作時,數據先被讀到內存中,然后再用數據寫到文件中,那么當你數據讀完時,我們如果這時調用close()方法關閉讀寫流,這時就可能造成數據丟失,為什么呢?因為,讀入數據完成時不代表寫入數據完成,一部分數據可能會留在緩存區中,這個時候flush()方法就格外重要了。

好了,接下來close使用代碼如下:

即便是flush方法寫出了數據,操作的最后還是要調用close方法,釋放系統資源。

FileWriter的續寫和換行

續寫和換行:操作類似于FileOutputStream操作(上一篇博客講到過),直接上代碼:

FileReader和FileWriter類完成文本文件復制

直接上代碼:

史上最騷最全最詳細的IO流教程,沒有之一

 

最后再次強調:
字符流,只能操作文本文件,不能操作圖片,視頻等非文本文件。當我們單純讀或者寫文本文件時 使用字符流 其他情況使用字節流

IO異常的處理

我們在學習的過程中可能習慣把異常拋出,而實際開發中并不能這樣處理,建議使用try...catch...finally 代碼塊,處理異常部分,格式代碼如下:

如果對異常不是特別熟練的童鞋可以參考這篇文章【java基礎之異常】死了都要try,不淋漓盡致地catch我不痛快!

好了,到這里,字符流Reader和Writer的故事的到這里了!

前面主要寫了一些基本的流作為IO流的入門。從這里開始將要見識一些更強大的流。比如能夠高效讀寫的緩沖流,能夠轉換編碼的轉換流,能夠持久化存儲對象的序列化流等等,而這些強大的流都是在基本的流對象基礎之上而來的!這些強大的流將伴隨著我們今后的開發!

1、緩沖流【掌握】

1.1 簡要概述

首先我們來認識認識一下緩沖流,也叫高效流,是對4個FileXxx 流的“增強流”。

緩沖流的基本原理

1、使用了底層流對象從具體設備上獲取數據,并將數據存儲到緩沖區的數組內。
2、通過緩沖區的read()方法從緩沖區獲取具體的字符數據,這樣就提高了效率。
3、如果用read方法讀取字符數據,并存儲到另一個容器中,直到讀取到了換行符時,將另一個容器臨時存儲的數據轉成字符串返回,就形成了readLine()功能。

也就是說在創建流對象時,會創建一個內置的默認大小的緩沖區數組,通過緩沖區讀寫,減少系統IO次數,從而提高讀寫的效率。

緩沖書寫格式為BufferedXxx,按照數據類型分類:

  • 字節緩沖流:BufferedInputStream,BufferedOutputStream
  • 字符緩沖流:BufferedReader,BufferedWriter

1.2 字節緩沖流

構造方法

  • public BufferedInputStream(InputStream in) :創建一個新的緩沖輸入流,注意參數類型為InputStream
  • public BufferedOutputStream(OutputStream out): 創建一個新的緩沖輸出流,注意參數類型為OutputStream

構造舉例代碼如下:

感受緩沖流的高效

緩沖流讀寫方法與基本的流是一致的,我們通過復制370多MB的大文件,測試它的效率。

  1. 基本流,代碼如下:
  1. 緩沖流,代碼如下:

有的童鞋就要說了,我要更快的速度!最近看速度與激情7有點上頭,能不能再快些?答案是當然可以

想要更快可以使用數組的方式,代碼如下:

1.3 字符緩沖流

構造方法

相同的來看看其構造,其格式以及原理和字節緩沖流是一樣一樣的!

  • public BufferedReader(Reader in) :創建一個新的緩沖輸入流,注意參數類型為Reader
  • public BufferedWriter(Writer out): 創建一個新的緩沖輸出流,注意參數類型為Writer

構造舉例,代碼如下:

字符緩沖流特有方法

字符緩沖流的基本方法與普通字符流調用方式一致,這里不再闡述,我們來看字符緩沖流具備的特有方法。

  • BufferedReader:public String readLine(): 讀一行數據。 讀取到最后返回null
  • BufferedWriter:public void newLine(): 換行,由系統屬性定義符號。

readLine方法演示代碼如下:

newLine方法演示代碼如下:

1.4 字符緩沖流練習

字符緩沖流練習啥捏?先放松一下吧各位,先欣賞欣賞我寫的下面的詩篇

6.你說你的程序叫簡單,我說我的代碼叫詩篇
1.一想到你我就哦豁豁豁豁豁豁豁豁豁豁....哦nima個頭啊,完全不理人家受得了受不了
8.Just 簡單你和我 ,Just 簡單程序員
3.約了地點卻忘了見面 ,懂得寂寞才明白浩瀚
5.沉默是最大的發言權
2.總是喜歡坐在電腦前, 總是喜歡工作到很晚
7.向左走 又向右走,我們轉了好多的彎
4.你從來就不問我,你還是不是那個程序員

欣賞完了咩?沒錯咋們就練習如何使用緩沖流的技術把上面的詩篇歸順序,都編過號了~就是前面的1到8的編號~

分析:首先用字符輸入緩沖流創建個源,里面放沒有排過序的文字,之后用字符輸出緩沖流創建個目標接收,排序的過程就要自己寫方法了哦,可以從每條詩詞的共同點“.”符號下手!

代碼實現

運行效果

2、轉換流【掌握】

何謂轉換流?為何由來?暫時帶著問題讓我們先來了解了解字符編碼和字符集!
 

史上最騷最全最詳細的IO流教程,沒有之一

 

2.1 字符編碼與解碼

眾所周知,計算機中儲存的信息都是用二進制數表示的,而我們在屏幕上看到的數字、英文、標點符號、漢字等字符是二進制數轉換之后的結果。按照某種規則,將字符存儲到計算機中,稱為編碼 。反之,將存儲在計算機中的二進制數按照某種規則解析顯示出來,稱為解碼。比如說,按照A規則存儲,同樣按照A規則解析,那么就能顯示正確的文本符號。反之,按照A規則存儲,再按照B規則解析,就會導致亂碼現象。

簡單一點的說就是:

編碼:字符(能看懂的)--字節(看不懂的)

解碼:字節(看不懂的)-->字符(能看懂的)

代碼解釋則是

  • 字符編碼 Character Encoding: 就是一套自然語言的字符與二進制數之間的對應規則。而編碼表則是生活中文字和計算機中二進制的對應規則

字符集

  • 字符集 Charset:也叫編碼表。是一個系統支持的所有字符的集合,包括各國家文字、標點符號、圖形符號、數字等。

計算機要準確的存儲和識別各種字符集符號,需要進行字符編碼,一套字符集必然至少有一套字符編碼。常見字符集有ASCII字符集、GBK字符集、Unicode字符集等。
 

史上最騷最全最詳細的IO流教程,沒有之一

 

可見,當指定了編碼,它所對應的字符集自然就指定了,所以編碼才是我們最終要關心的。

  • ASCII字符集 :ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼)是基于拉丁字母的一套電腦編碼系統,用于顯示現代英語,主要包括控制字符(回車鍵、退格、換行鍵等)和可顯示字符(英文大小寫字符、阿拉伯數字和西文符號)。基本的ASCII字符集,使用7位(bits)表示一個字符,共128字符。ASCII的擴展字符集使用8位(bits)表示一個字符,共256字符,方便支持歐洲常用字符。
  • ISO-8859-1字符集:拉丁碼表,別名Latin-1,用于顯示歐洲使用的語言,包括荷蘭、丹麥、德語、意大利語、西班牙語等。ISO-8859-1使用單字節編碼,兼容ASCII編碼。
  • GBxxx字符集:GB就是國標的意思,是為了顯示中文而設計的一套字符集。GB2312:簡體中文碼表。一個小于127的字符的意義與原來相同。但兩個大于127的字符連在一起時,就表示一個漢字,這樣大約可以組合了包含7000多個簡體漢字,此外數學符號、羅馬希臘的字母、日文的假名們都編進去了,連在ASCII里本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這就是常說的"全角"字符,而原來在127號以下的那些就叫"半角"字符了。GBK:最常用的中文碼表。是在GB2312標準基礎上的擴展規范,使用了雙字節編碼方案,共收錄了21003個漢字,完全兼容GB2312標準,同時支持繁體漢字以及日韓漢字等。GB18030:最新的中文碼表。收錄漢字70244個,采用多字節編碼,每個字可以由1個、2個或4個字節組成。支持中國國內少數民族的文字,同時支持繁體漢字以及日韓漢字等。
  • Unicode字符集 :Unicode編碼系統為表達任意語言的任意字符而設計,是業界的一種標準,也稱為統一碼、標準萬國碼。它最多使用4個字節的數字來表達每個字母、符號,或者文字。有三種編碼方案,UTF-8、UTF-16和UTF-32。最為常用的UTF-8編碼。UTF-8編碼,可以用來表示Unicode標準中任何字符,它是電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼。互聯網工程工作小組(IETF)要求所有互聯網協議都必須支持UTF-8編碼。所以,我們開發Web應用,也要使用UTF-8編碼。它使用一至四個字節為每個字符編碼,編碼規則:128個US-ASCII字符,只需一個字節編碼。拉丁文等字符,需要二個字節編碼。大部分常用字(含中文),使用三個字節編碼。其他極少使用的Unicode輔助字符,使用四字節編碼。

2.2 編碼問題導致亂碼

在java開發工具IDEA中,使用FileReader 讀取項目中的文本文件。由于IDEA的設置,都是默認的UTF-8編碼,所以沒有任何問題。但是,當讀取Windows系統中創建的文本文件時,由于Windows系統的默認是GBK編碼,就會出現亂碼。

那么如何讀取GBK編碼的文件呢? 這個時候就得講講轉換流了!

從另一角度來講:字符流=字節流+編碼表

2.3 InputStreamReader類-----(字節流到字符流的橋梁)

轉換流java.io.InputStreamReader,是Reader的子類,從字面意思可以看出它是從字節流到字符流的橋梁。它讀取字節,并使用指定的字符集將其解碼為字符。它的字符集可以由名稱指定,也可以接受平臺的默認字符集。

構造方法

InputStreamReader(InputStream in): 創建一個使用默認字符集的字符流。
InputStreamReader(InputStream in, String charsetName): 創建一個指定字符集的字符流。

構造代碼如下:

使用轉換流解決編碼問題

2.4 OutputStreamWriter類-----(字符流到字節流的橋梁)

轉換流java.io.OutputStreamWriter ,是Writer的子類,字面看容易混淆會誤以為是轉為字符流,其實不然,OutputStreamWriter為從字符流到字節流的橋梁。使用指定的字符集將字符編碼為字節。它的字符集可以由名稱指定,也可以接受平臺的默認字符集。

構造方法

OutputStreamWriter(OutputStream in): 創建一個使用默認字符集的字符流。
OutputStreamWriter(OutputStream in, String charsetName): 創建一個指定字符集的字符流。

構造舉例,代碼如下:

指定編碼構造代碼

史上最騷最全最詳細的IO流教程,沒有之一

 


為了達到最高效率,可以考慮在 BufferedReader 內包裝 InputStreamReader

3、序列化流【理解】

(1)可以把對象寫入文本文件或者在網絡中傳輸
(2)如何實現序列化呢?
讓被序列化的對象所屬類實現序列化接口。
該接口是一個標記接口。沒有功能需要實現。
(3)注意問題:
把數據寫到文件后,在去修改類會產生一個問題。
如何解決該問題呢?
在類文件中,給出一個固定的序列化id值。
而且,這樣也可以解決黃色警告線問題
(4)面試題:
什么時候序列化?
如何實現序列化?
什么是反序列化?

3.1 何謂序列化

Java 提供了一種對象序列化的機制。用一個字節序列可以表示一個對象,該字節序列包含該對象的數據、對象的類型和對象中存儲的屬性等信息。字節序列寫出到文件之后,相當于文件中持久保存了一個對象的信息。

反之,該字節序列還可以從文件中讀取回來,重構對象,對它進行反序列化。對象的數據、對象的類型和對象中存儲的數據信息,都可以用來在內存中創建對象。看圖理解序列化:
 

史上最騷最全最詳細的IO流教程,沒有之一

 

3.2 ObjectOutputStream類

java.io.ObjectOutputStream 類,將Java對象的原始數據類型寫出到文件,實現對象的持久存儲。

構造方法

public ObjectOutputStream(OutputStream out): 創建一個指定OutputStream的ObjectOutputStream。

構造代碼如下:

序列化操作

  1. 一個對象要想序列化,必須滿足兩個條件:

該類必須實現java.io.Serializable 接口,Serializable 是一個標記接口,不實現此接口的類將不會使任何狀態序列化或反序列化,會拋出NotSerializableException 。

該類的所有屬性必須是可序列化的。如果有一個屬性不需要可序列化的,則該屬性必須注明是瞬態的,使用transient 關鍵字修飾。

2.寫出對象方法

public final void writeObject (Object obj) : 將指定的對象寫出。

3.3 ObjectInputStream類

ObjectInputStream反序列化流,將之前使用ObjectOutputStream序列化的原始數據恢復為對象。

構造方法

public ObjectInputStream(InputStream in): 創建一個指定InputStream的ObjectInputStream。

反序列化操作1

如果能找到一個對象的class文件,我們可以進行反序列化操作,調用ObjectInputStream讀取對象的方法:

  • public final Object readObject () : 讀取一個對象。

對于JVM可以反序列化對象,它必須是能夠找到class文件的類。如果找不到該類的class文件,則拋出一個 ClassNotFoundException 異常。

反序列化操作2

另外,當JVM反序列化對象時,能找到class文件,但是class文件在序列化對象之后發生了修改,那么反序列化操作也會失敗,拋出一個InvalidClassException異常。發生這個異常的原因如下:

1、該類的序列版本號與從流中讀取的類描述符的版本號不匹配
2、該類包含未知數據類型
2、該類沒有可訪問的無參數構造方法

Serializable 接口給需要序列化的類,提供了一個序列版本號。serialVersionUID 該版本號的目的在于驗證序列化的對象和對應類是否版本匹配。

3.4 序列化集合練習

  1. 將存有多個自定義對象的集合序列化操作,保存到list.txt文件中。
  2. 反序列化list.txt ,并遍歷集合,打印對象信息。

案例分析

  1. 把若干學生對象 ,保存到集合中。
  2. 把集合序列化。
  3. 反序列化讀取時,只需要讀取一次,轉換為集合類型。
  4. 遍歷集合,可以打印所有的學生信息

案例代碼實現

4、打印流【掌握】

4.1 何謂打印流

平時我們在控制臺打印輸出,是調用print方法和println方法完成的,各位用了這么久的輸出語句肯定沒想過這兩個方法都來自于java.io.PrintStream類吧,哈哈。該類能夠方便地打印各種數據類型的值,是一種便捷的輸出方式。

打印流分類

字節打印流PrintStream,字符打印流PrintWriter

打印流特點

A:只操作目的地,不操作數據源
B:可以操作任意類型的數據
C:如果啟用了自動刷新,在調用println()方法的時候,能夠換行并刷新
D:可以直接操作文件

這個時候有同學就要問了,哪些流可以直接操作文件呢?答案很簡單,如果該流的構造方法能夠同時接收File和String類型的參數,一般都是可以直接操作文件的

PrintStream是OutputStream的子類,PrintWriter是Writer的子類,兩者處于對等的位置上,所以它們的API是非常相似的。二者區別無非一個是字節打印流,一個是字符打印流。

4.2 字節輸出打印流PrintStream復制文本文件

4.3 字符輸出打印流PrintWriter復制文本文件

5、Properties屬性類

我想各位對這個Properties類多多少少也接觸過了,首先Properties類并不在IO包下,那為啥要和IO流一起講呢?原因很簡單因為properties類經常和io流的聯合一起使用。

(1)是一個集合類,Hashtable的子類
(2)特有功能
A:public Object setProperty(String key,String value)
B:public String getProperty(String key)
C:public Set stringPropertyNames()
(3)和IO流結合的方法
把鍵值對形式的文本文件內容加載到集合中
public void load(Reader reader)
public void load(InputStream inStream)
把集合中的數據存儲到文本文件中
public void store(Writer writer,String comments)
public void store(OutputStream out,String comments)

5.1 Properties概述

java.util.Properties 繼承于Hashtable ,來表示一個持久的屬性集。它使用鍵值結構存儲數據,每個鍵及其對應值都是一個字符串。該類也被許多Java類使用,比如獲取系統屬性時,System.getProperties 方法就是返回一個Properties對象。

5.2 Properties類

構造方法

public Properties() :創建一個空的屬性列表。

基本的存儲方法

  • public Object setProperty(String key, String value) : 保存一對屬性。
  • public String getProperty(String key) :使用此屬性列表中指定的鍵搜索屬性值。
  • public Set<String> stringPropertyNames() :所有鍵的名稱的集合。

與流相關的方法

public void load(InputStream inStream): 從字節輸入流中讀取鍵值對。

參數中使用了字節輸入流,通過流對象,可以關聯到某文件上,這樣就能夠加載文本中的數據了。現在文本數據格式如下:

加載代碼演示:

文本中的數據,必須是鍵值對形式,可以使用空格、等號、冒號等符號分隔。

怎么說呢,io流的基礎回顧就先告一段落了,淺嘗輒止。循序漸進,實踐中慢慢總結!更何況我還很low,依舊任重而道遠。

現在jdk已經出到13了,io流也有了許多的變化。有時間會從頭整理一下,一定會有機會的!

分享到:
標簽:IO
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定