今天寫一個(gè)讀寫程序,運(yùn)用到InputStream的reset方法是發(fā)現(xiàn)竟然失敗了,然后查了一下JDK源碼,發(fā)現(xiàn)BufferInputStream重寫了父類FilterInputStream的mark和resetf方法,其有支持 mark 和 reset 方法的能力。而FileInputStream則沒有重寫父類InputStream的這兩個(gè)方法,其不具有mark和reset方法的能力。
在JDK源碼中,寫到public synchronized void mark(int readlimit)在該輸入流中標(biāo)記當(dāng)前位置。 后續(xù)調(diào)用 reset 方法重新將流定位于最后標(biāo)記位置,以便后續(xù)讀取能重新讀取相同字節(jié)。
readlimit 參數(shù)給出當(dāng)前輸入流在標(biāo)記位置變?yōu)榉欠ㄇ霸试S讀取的字節(jié)數(shù)。
這句話的意思是說(shuō):mark就像書簽一樣,用于標(biāo)記,以后再調(diào)用reset時(shí)就可以再回到這個(gè)mark過(guò)的地方。mark方法有個(gè)參數(shù),通過(guò)這個(gè)整型參數(shù),你告訴系統(tǒng),希望在讀出這么多個(gè)字符之前,這個(gè)mark保持有效。比如說(shuō)mark(10),那么在read()10個(gè)以內(nèi)的字符時(shí),reset()操作后可以重新讀取已經(jīng)讀出的數(shù)據(jù),如果已經(jīng)讀取的數(shù)據(jù)超過(guò)10個(gè),那reset()操作后,就不能正確讀取以前的數(shù)據(jù)了,因?yàn)榇藭r(shí)mark標(biāo)記已經(jīng)失效。
下面是BufferInputStream以及父類FilterInputStream 中這兩個(gè)方法的默認(rèn)實(shí)現(xiàn)//FilterInputStream.java
public synchronized void mark(int readlimit) {in.mark(readlimit);
}
public synchronized void reset() throws IOException {in.reset();
}
br>public boolean markSupported() {br> return in.markSupported()br>}
//BufferedInputStream.java
public synchronized void mark(int readlimit) {marklimit = readlimit;
markpos = pos;
}
public synchronized void reset() throws IOException {getBufIfOpen(); // Cause exception if closedif (markpos 0)
throw new IOException("Resetting to invalid mark");pos = markpos;
}br>br>
public boolean markSupported() {
return true;
} //支持mark操作
而FileInputStream沒有重寫父類InputStream的默認(rèn)實(shí)現(xiàn),其默認(rèn)實(shí)現(xiàn)如下:
//InputStream.java
public synchronized void mark(int readlimit) {}//空實(shí)現(xiàn)什么都沒有實(shí)現(xiàn)public synchronized void reset() throws IOException {throw new IOException("mark/reset not supported");}//不支持reset操作
public boolean markSupported() {
return false;
} //不支持mark操作
下面是一個(gè)簡(jiǎn)單的程序,用于設(shè)置reset和mark.
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class TestInputStream {
public void read(InputStream in) throws IOException {if(in == null) {
return;
}
int len=0;
in.mark(1);
in.read() //第一次讀取
in.reset();//又可以重新讀取
in.read()//第二次讀取跟第一次讀取結(jié)果一樣。因?yàn)橹蛔x了一個(gè),沒有超過(guò)mark設(shè)置的整數(shù)。所以mark有效}
public static void main(String[] args) throws IOException {TestInputStream test = new TestInputStream();String fileName = "F:/Google.txt";
InputStream in1 = new FileInputStream(new File(fileName));if(!in1.markSupported()) {
in1 = new BufferedInputStream(in1);
}
test.read(in1);
byte[] buf = new byte[100];
while(in1.read(buf, 0, buf.length)!=-1) {System.out.println(buf);
}
System.out.println("Success!");
}
}
總結(jié):
mark
public void mark(int readlimit)
mark 的常規(guī)協(xié)定是:如果方法 markSupported 返回 true,那么輸入流總是在調(diào)用 mark 之后記錄所有讀取的字節(jié),并時(shí)刻準(zhǔn)備在調(diào)用方法 reset 時(shí)(無(wú)論何時(shí)),再次提供這些相同的字節(jié)。但是,如果在調(diào)用 reset 之前可以從流中讀取多于 readlimit 的字節(jié),則不需要該流記錄任何數(shù)據(jù)。
參數(shù):
readlimit - 在標(biāo)記位置失效前可以讀取字節(jié)的最大限制。
4 reset
public void reset() throws IOException
將此流重新定位到最后一次對(duì)此輸入流調(diào)用 mark 方法時(shí)的位置。
reset 的常規(guī)協(xié)定是:
1、如果方法 markSupported 返回 true,那么:
如果創(chuàng)建流以后未調(diào)用方法 mark,或最后調(diào)用 mark 以后從該流讀取的字節(jié)數(shù)大于最后調(diào)用 mark 時(shí)的參數(shù),則可能拋出 IOException。
如果未拋出這樣的 IOException,則將該流重新設(shè)置為這種狀態(tài):最近一次調(diào)用 mark 以后(如果未調(diào)用過(guò) mark,則從文件開頭開始)讀取的所有字節(jié)將重新提供給 read 方法的后續(xù)調(diào)用者,后跟任何從調(diào)用 reset 時(shí)起將作為下一輸入數(shù)據(jù)的字節(jié)。
2、如果方法 markSupported 返回 false,那么:
對(duì) reset 的調(diào)用可能拋出 IOException。
如果未拋出 IOException,則將該流重新設(shè)置為一種固定狀態(tài),該狀態(tài)取決于輸入流的特定類型及其創(chuàng)建方式。提供給 read 方法后續(xù)調(diào)用者的字節(jié)取決于特定類型的輸入流。
除了拋出 IOException 之外,類 InputStream 的方法 reset 不執(zhí)行任何操作。
拋出:
IOException - 如果未標(biāo)記此流或該標(biāo)記失效。
以上就是在linux系統(tǒng)中InputStream輸入流的方法的注意事項(xiàng),謝謝閱讀,希望能幫到大家,請(qǐng)繼續(xù)關(guān)注腳本之家,我們會(huì)努力分享更多優(yōu)秀的文章。