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