Java學習里程-----Java基礎_23 Java IO 流(二)

繼續,順着《Java學習里程-----Java基礎_23 Java IO 流(一)》這個,接着來

六、字節流

(先打開Java Api開發手冊,沒有的同學 -> https://docs.oracle.com/javase/8/docs/api/  )

字節流中,輸入流的祖類,InputStream

這個是一個抽象類,無法直接實例化,只能實例化他的子類。它的子類有(看 Direct Known Subclasses 的下面)

是吧,子類很多的,而且這個InputStream還實現了Closeable接口,這個我們後面再去說這個Closeable接口。

輸出流的祖類是 OutputStream,同樣搜索一下

是吧,同樣也是一個抽象類,它下面的子類也有很多,但是不如InputStream多,多不多沒有啥關係,無所謂的。

瞭解了一下字節流的類之後,我們可以寫個demo進行測試測試。

七、InputStream

我們剛纔說過,InputStream是一個抽象類,需要由子類來進行具體的實現,我們先使用FileInputStream來實現一下。

打開eclipse,我還在我原有的Test工程上進行編寫。(當然這樣的做法是不對的,我建議大家自己創建一個新的類,然後進行代碼的編寫,不要養成習慣,每次Test,每次Test,這樣不好,而且到時候你找代碼的時候你都找不到。)

我們可以看到啊,在使用FileInputStream這個子類的時候呢,有三種方式進行實例化,各有各的不同。

第一種是傳一個file,我一般都用這個。第二種傳入一個FileDescriptor 類型的參數,說實話,我沒有用過第二種這個。第三種是傳入一個文件路徑即可,這個也可以,但是也不是常用。我個人傾向於第一種,傳入一個file。但是這裏我們三種都會講述。

 

雖說這個是字節流,但是因爲我們的輸出窗口弄不出來圖片顯示,所以我們就不弄圖片了,我們弄一段文字來測試一下,大家在自己的桌面上創建一個txt的文本,當然,不帶要弄得話,我下面會上傳一下這個附件,我們來讀取一下里面的內容,內容的話中文英文無所謂,文件名也是中英文無所謂。

我們來讀取一下桌面上的這個txt文件

進來就能看到這個課件,直接下載就好

第一種方法:我們先來用傳入一個file的構造器來構造FileInputStream

先創建一個File,然後給一個文件地址。

文件地址,在txt鼠標右鍵,最後一個屬性,自己查看。

注意啊,實例化File這個類的時候用的 java.io.File 下面的File,別導入錯了包。

然後實例化InputStream。這裏會有異常,我們來捕獲一下異常。

然後怎麼讀取文件裏面的內容呢?

我們用 inputStream.read() 去讀取內容。

我們點進去可以看到,讀完之後會返回一個int類型的值,這個就是一個二進制的數字,我們用一個int類型的變量去獲取上這個值。(這裏還得捕獲一下異常)

現在我們輸出一下這個i,我們先來看一下是什麼。

輸出了一個229.

很明顯啊,不對,因爲這個229我們文本里面沒有,二呢,我們也不知道229是對應的什麼。這裏我們看一下源碼是怎麼描述的

鼠標指針指導read,按ctrl ,然後鼠標左鍵點進去。或者你直接從api中查找。找到直接Google翻譯一下。

這段話說的是這個read方法,從輸入流中讀取下一個數據字節。等到讀讀讀,讀到-1的時候,說明就讀取完成了。so,我們需要用到循環,將這個讀取出來。我們修改一下代碼

如果讀取到的東西不是-1,我們就一直讀取,然後將讀取之後的數字我們存放到一個byte數組中。

這樣,然後我們輸出,輸出什麼呢,將這個b進行轉換,轉換成String類型。

寫到這裏爲止,我們可以看到一個感嘆號,我們不要管這個感嘆號,我們先運行。

很好報錯了,報錯的原因是什麼呢?

我們移動到這個b 上面,它的意思是說:這個b 不能是空的去運行,需要給一個初始值。我們這裏給他弄好初始值,給它1024個單位。

再來運行。

我們會發現還有錯誤,這個錯誤是說,我們其實後面還在讀取,但是你的這個byte存放不下了,導致len++這個數字已經超過了1024,byte但是最大也就1024個空,沒有多的了,所以報錯了,這個我們給大一點byte數組的長度。我給成2048,試一下。

是OK的,沒問題,讀取出來了,但是,新的問題又來了,不要慌,我們來分析一下爲什麼。

首先,一箇中文呢是兩個字節。而我們在使用InputStream讀取的時候是按照一個字節一個字節去讀取。

找到問題之後,我們來想辦法解決。

System.out.println(new String(b, "utf8")); 我們只需要再輸出的時候按照utf8的格式去輸出就好。

除去這樣的寫法之外,還有一種是直接創建一個byte數組,然後read,傳入這個byte輸出,最後將byte數組轉換成String類型進行輸出。

我很喜歡這樣的方式,當然,上面的方式也可以,這個大家自己選擇,比較條條大路通羅馬嗎。

上面的就是一個字節一個字節的去讀取,下面是一起讀取,就這點差別。我們來測試一下長一點的文本,我們來看一下用的時間是多少,因爲後面我們要會和字符流進行對比。

long start = System.currentTimeMillis();

我們用這個來獲取一下開始時間。

long end = System.currentTimeMillis();

這個獲取結束時間,這兩個時間都是long類型,我們到時候一算差就知道花了多久了。

我換一個文本進行讀取,找一個比較長的。

不幸的是,這個文章也不怎麼長,我這裏本地讀取也就3~4毫秒就OK了。

我們再看一下另外一個方法。

32 ~ 44 毫秒之間,說明,一起讀取要比這個一個一個讀取快。

so 我們推薦整體讀取。

第二種方法:我們再來用傳入一個String的構造器來構造FileInputStream

這樣也是可以的,其實。我們可以看一下源碼。

它底層其實還是弄了一個file,只是我們調用的人看不到而已。

第三種方法:最後一個方法,我們用傳入FileDescriptor的構造器來構造FileInputStream

我明說,搞不懂,屬實不會,有興趣的同學自行研究,我是從事Java開發到現在,沒有用到過。我個人建議,會用好上面內兩個就OK了。

八、關閉流

其實,我一直都沒有說這個問題啊,在我們學習這個流的過程中,有很重要的一步,就是關閉流。因爲流再開啓的時候,你要是不關閉,這玩意是很耗內存的,就像水龍頭,用完要記得關閉,忘記關那得浪費多少水啊。

所以,我們需要在catch之後的finally方法中加一個

切記 一定要加!!!不管是字符流還是字節流,輸入流輸出流,用完一定要關閉。!!!

一定要關閉!

我們這節就講到這裏,下一節我們開始說OutputStream。記得點點關注,小心心。

課件大家自己去下載哦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章