摘要:關(guān)閉此輸入流并釋放與該流關(guān)聯(lián)的所有系統(tǒng)資源。在此輸入流中標(biāo)記當(dāng)前的位置。從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲(chǔ)在緩沖區(qū)數(shù)組中。將此流重新定位到最后一次對(duì)此輸入流調(diào)用方法時(shí)的位置。
一、寫(xiě)在前面
在Java中流的一系列操作,可能會(huì)感到既熟悉又陌生。熟悉是因?yàn)楹芑A(chǔ)且出鏡率很高,陌生對(duì)大多數(shù)程序員平時(shí)工作中很少寫(xiě)相關(guān)的代碼。
~~ 我是很少寫(xiě)~~
回歸正題,本章我不不是探討流,主要來(lái)說(shuō)下造成‘標(biāo)題’問(wèn)題的原因。
問(wèn)題很簡(jiǎn)單,稍微看下源碼或者debug下就可以找到問(wèn)題所在,這是一些細(xì)節(jié)問(wèn)題,既然出現(xiàn)了在此做下記錄,給自己一個(gè)警惕。
二、場(chǎng)景引入今天微信上突然收到前同事一段這樣的問(wèn)題描述
在讀取文件時(shí)如果文件為空、導(dǎo)致進(jìn)入while死循環(huán),
并附上一段代碼。
/** * 將文件數(shù)據(jù)流寫(xiě)入到zip流中 * * @param fileName * @param inputStream * @param outputStream * @throws IOException */ public static void zipInputStream(String fileName, InputStream inputStream, ZipOutputStream outputStream) throws IOException { try { BufferedInputStream bInStream = new BufferedInputStream(inputStream); outputStream.putNextEntry(new ZipEntry(fileName)); byte[] buffer = new byte[inputStream.available()]; int r = 0; while ((r = bInStream.read(buffer)) != -1) { outputStream.write(buffer, 0, r); } outputStream.closeEntry(); } catch (IOException e) { throw e; } finally { if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { throw e; } } } }
咋一看這段代碼也沒(méi)啥問(wèn)題!~是不是~
三、解決思路我們一點(diǎn)點(diǎn)的來(lái)分析下
首先陷入while死循環(huán)的條件bInStream.read(buffer)) != -1
while ((r = bInStream.read(buffer)) != -1) { outputStream.write(buffer, 0, r); }
看下源碼中的描述,
/** * Reads up tolen
bytes of data from this input stream * into an array of bytes. Iflen
is not zero, the method * blocks until some input is available; otherwise, no * bytes are read and0
is returned. ** This method simply performs
in.read(b, off, len)
* and returns the result. * * @param b the buffer into which the data is read. * @param off the start offset in the destination arrayb
* @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or *-1
if there is no more data because the end of * the stream has been reached. * @exception NullPointerException Ifb
isnull
. * @exception IndexOutOfBoundsException Ifoff
is negative, *len
is negative, orlen
is greater than *b.length - off
* @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in */ public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); }
上面描述有這么一段,如果byte[]數(shù)組的len為0則不做任何操作直接返回0。
看到這問(wèn)題基本就可以定位了,在看代碼中byte[]的定義。
byte[] buffer = new byte[inputStream.available()];
看到這小伙們就笑了inputStream.available(),你讀的是一個(gè)空文件可不是為0。
/** * Returns an estimate of the number of bytes that can be read (or * skipped over) from this input stream without blocking by the next * caller of a method for this input stream. The next caller might be * the same thread or another thread. A single read or skip of this * many bytes will not block, but may read or skip fewer bytes. ** This method returns the result of {@link #in in}.available(). * * @return an estimate of the number of bytes that can be read (or skipped * over) from this input stream without blocking. * @exception IOException if an I/O error occurs. */ public int available() throws IOException { return in.available(); }
描述的很清楚,返回此輸入流下一個(gè)方法調(diào)用可以不受阻塞地從此輸入流讀?。ɑ蛱^(guò))的估計(jì)字節(jié)數(shù)。
說(shuō)到這基本就反應(yīng)過(guò)來(lái),再說(shuō)就有點(diǎn)啰嗦了。
四、總結(jié)像這種問(wèn)題其實(shí)和技術(shù)和能力沒(méi)多大關(guān)系、主要是細(xì)心和經(jīng)驗(yàn)。其實(shí)定義一個(gè)程序員的牛逼與否在于他踩過(guò)的坑是否足夠多。
既然說(shuō)到這那就順便溫故下InputStream的幾個(gè)方法吧!
int available() : 返回此輸入流下一個(gè)方法調(diào)用可以不受阻塞地從此輸入流讀?。ɑ蛱^(guò))的估計(jì)字節(jié)數(shù)。void close() : 關(guān)閉此輸入流并釋放與該流關(guān)聯(lián)的所有系統(tǒng)資源。
void mark(int readlimit): 在此輸入流中標(biāo)記當(dāng)前的位置。
boolean markSupported() : 測(cè)試此輸入流是否支持 mark 和 reset 方法。
abstract int read() : 測(cè)試此輸入流是否支持 mark 和 reset 方法。
int read(byte[] b) : 從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲(chǔ)在緩沖區(qū)數(shù)組 b 中。
int read(byte[] b, int off, int len) : 將輸入流中最多 len 個(gè)數(shù)據(jù)字節(jié)讀入 byte 數(shù)組。
void reset() : 將此流重新定位到最后一次對(duì)此輸入流調(diào)用 mark 方法時(shí)的位置。
long skip(long n) : 跳過(guò)和丟棄此輸入流中數(shù)據(jù)的 n 個(gè)字節(jié)。
以次簡(jiǎn)單的問(wèn)題來(lái)對(duì)InputStream 溫故。
如有分析的錯(cuò)誤的地方、歡迎指正
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74640.html
摘要:不同類(lèi)型的流入,往往對(duì)應(yīng)于不同類(lèi)型的流數(shù)據(jù)。所以通常會(huì)將字節(jié)緩存到一定數(shù)量后再發(fā)送。如果是,則將兩個(gè)標(biāo)記都拋棄并且將之前的內(nèi)容作為一行返回。因此二者陷入死鎖。因此推出了和類(lèi)。 前言 最近在重拾Java網(wǎng)絡(luò)編程,想要了解一些JAVA語(yǔ)言基本的實(shí)現(xiàn),這里記錄一下學(xué)習(xí)的過(guò)程。 閱讀之前,你需要知道 網(wǎng)絡(luò)節(jié)點(diǎn)(node):位于網(wǎng)絡(luò)上的互相連通的設(shè)備,通常為計(jì)算機(jī),也可以是打印機(jī),網(wǎng)橋,路由器等...
摘要:不建議對(duì)這兩個(gè)對(duì)象嘗試使用單個(gè)線程,因?yàn)檫@樣可能會(huì)造成該線程死鎖。構(gòu)造函數(shù)創(chuàng)建尚未連接到管道輸入流的管道輸出流。通常,數(shù)據(jù)由某個(gè)線程從對(duì)象讀取,并由其他線程將其寫(xiě)入到相應(yīng)的。 管道流 管道流的主要作用是可以進(jìn)行兩個(gè)線程間的通訊,分為管道輸出流(PipedOutputStream)、管道輸入流(PipedInputStream),如果想要進(jìn)行管道輸出,則必須要把輸出流連在輸入流之上,在...
小編寫(xiě)這篇文章的主要目的,是用來(lái)給大家做一個(gè)介紹的,介紹關(guān)于在Python中。流程控制條件一些問(wèn)題,另外還有如何進(jìn)行for循環(huán)呢?下面小編給大家詳細(xì)的進(jìn)行闡述一下。1、if條件選擇 #coding:utf-8 num=23 ifnum>2: print("dayu") ifnum<2: print("xiaoyu") ...
摘要:遇到的問(wèn)題在用通信傳輸一個(gè)文件以及其他的非文件的時(shí)候總是傳到服務(wù)端的文件出錯(cuò),后來(lái)發(fā)現(xiàn)是在用字符流和字節(jié)流在讀取各種文件上的差別所導(dǎo)致的讀取文件的方式字節(jié)流讀取和,其讀取的方式按字節(jié)讀取,這個(gè)常用于讀取原始數(shù)據(jù)。 遇到的問(wèn)題 在用socket通信傳輸一個(gè)pdf文件以及其他的非txt文件的時(shí)候總是傳到服務(wù)端的文件出錯(cuò),后來(lái)發(fā)現(xiàn)是在用字符流和字節(jié)流在讀取各種文件上的差別所導(dǎo)致的 java讀...
小編寫(xiě)這篇文章的主要目的,主要是給大家做一個(gè)比較詳細(xì)的解答,因?yàn)楹芏嗳嗽谑褂胮ython的時(shí)候,往往會(huì)遇到各種各樣的問(wèn)題,比如if控制語(yǔ)句和for循環(huán)這些內(nèi)容,不能夠合理地進(jìn)行運(yùn)用,那么,具體要怎么使用呢?下面小編就給大家詳細(xì)解答下?! ?、if條件選擇 #coding:utf-8 num=23 ifnum>2: print("dayu") i...
閱讀 3950·2021-11-16 11:50
閱讀 947·2021-11-11 16:55
閱讀 3671·2021-10-26 09:51
閱讀 872·2021-09-22 15:03
閱讀 3438·2019-08-30 15:54
閱讀 3272·2019-08-30 15:54
閱讀 2482·2019-08-30 14:04
閱讀 927·2019-08-30 13:53