InputStream read()方法详解
在Java7中,InputStream被定義為一個抽象類,相應的,該類下的read()方法也是一個抽象方法,這也就意味著必須有一個類繼承InputStream并且實現這個read方法。
查閱Java7 API,我們可以看到,在InputStream中定義了三個重載的read()方法:
但是在這三個方法中,只有參數列表為空的read方法定義為抽象方法,這也就意味著在直接繼承自InputStream的所有子類中,必須重寫這個方法。下面我們來看看這個方法的介紹:
這里有兩點需要注意:一是這個方法的返回值是int類型;二是在這個方法每次從數據源中讀取一個byte并返回。很多初次接觸Java的讀者在看到這里時都會產生下面的疑問,就是這個方法讀取的byte是如何以int的形式返回的。
在計算機中,所有的文件都是以二進制的形式存儲的,換句話說,每個文件不管是什么類型,在計算機中的形式都是一串0和1。而read()方法在讀的時候是每次讀取8個二進制位,這8個0或1就是我們所謂的一個byte(字節)。在這里通常容易產生的疑問就是將字節和字符混為一談。無論在什么語言什么系統中,只要它符合當今世界對于計算機技術的主流定義,那么一個byte就是8個二進制位。而字符則不同,字符是與人為定義的編碼規則相關的,一個字符的大小(也就是其所占的二進制位)是由編碼規則決定的,比如在GBK編碼中一個漢字用兩個字節表示,而在utf-8中,一個漢字由3到4個字節表示。言歸正傳,既然一個byte表示8個二進制位,那么這8個二進制位就是一個0-255之間的十進制數字,實際上在Java中,byte就是一個0-255之間的整數,而將從文件中讀取的二進制轉化成十進制這一過程是由read()方法完成的。
也就是說,read()這個方法完成的事情就是從數據源中讀取8個二進制位,并將這8個0或1轉換成十進制的整數,然后將其返回。
下面再來看read(byte[] b)這個方法,這個方法的介紹如下:
這個方法使用一個byte的數組作為一個緩沖區,每次從數據源中讀取和緩沖區大小(二進制位)相同的數據并將其存在緩沖區中。當然byte數組中存放的仍然是0-255的整數,將二進制轉換為十進制這個過程仍然是read方法實現的。
需要注意的是,雖然我們可以指定緩沖區的大小,但是read方法在讀取數據的時候仍然是按照字節來讀取的。在utf-8等變長編碼中,一個復雜字符(比如漢字)所占字節往往大于1,并且長度往往是不固定的。(參照UTF-8編碼規則)按照字節讀取數據會將字符割裂,這就導致我們在使用read(byte[] b)方法讀取文件時,雖然指定了緩沖區的大小,但是仍然會出現亂碼。下面這段代碼可以很好地解釋這一點
文件如下(采用ANSI編碼):
運行結果如下:
補充一點:在調用new String(byte[] b)這個構造方法時,java會根據傳入的數據按照當前編碼規則創建String,如果將編碼方式改為GBK,則可以正常輸出中文:
這是因為,GBK編碼每個漢字占兩個字節,緩沖區大小設為2就可以避免字符編碼割裂的情況。
總結
以上是生活随笔為你收集整理的InputStream read()方法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 便宜好用的无线蓝牙耳机推荐:性价比超高的
- 下一篇: 塞班为什么那时候只有java_回忆S60