想要查看此教程的目錄請點擊:Java IO教程目錄貼地址
InputStream是Java IO中所有輸入流的基類。它的子類包括FileInputStream,BufferedInputStream和PushbackInputStream等。想要查看所有詳細的列表,請看“Java IO Overview”章節(jié)。
InputStreams and Sources
InputStream經常被用來連接一些數(shù)據(jù)源,例如文件,網絡連接,管道等等。查看更詳細的信息參考“Java IO Overview”章節(jié)
InputStream例子
它用來讀取字節(jié)數(shù)據(jù),每次讀取一個字節(jié)。下面是一個相關例子:
nputStream inputstream = new FileInputStream("c:\\data\\input-text.txt");
int data = inputstream.read();
while(data != -1) {
//do something with data...
doSomethingWithData(data);
data = inputstream.read();
}
inputstream.close();
這個例子中創(chuàng)建了一個FileInputStream實例。FileInputStream是InputStream的子類所以它可以InputStream類型的變量。
注意:為了代碼清晰,這里并沒有考慮處理異常的情況。想學習更多可以看“Java IO Exception Handling”
Java7開始,你可以用try-with-resources去確保InputStream在使用后可以關閉。具體的用法可以參考上面Java異常處理的文章,但是這里有一個例子:
try( InputStream inputstream = new FileInputStream("file.txt") ) {
int data = inputstream.read();
while(data != -1){
System.out.print((char) data);
data = inputstream.read();
}
}
只要線程已經執(zhí)行出try代碼塊,inputstream就會被關閉。
read()
InputStream的read()方法返回一個int類型的值,這個值是每次讀取的字節(jié)的值。下面是一個相關的例子:
int data = inputstream.read();
你也可以把int值強轉成為一個char類型的:
char aChar = (char) data;
InputStream的子類有可能擴展了read()方法。例如,DataInputStream允許讀取java基本類型,像int、long、float、double、boolean等等。當然這些有相應的方法,readBoolean(),readDouble()等等。
Stream的結束
如果read()方法返回 -1,就說明流到已經全部讀取完畢。這里的 -1 是int類型的,不是byte或short。這里是有些不同的!
當流去讀完畢的時候,你可以關閉它了
read(byte[])
InputStream有兩個read()方法,參數(shù)是一個字節(jié)數(shù)組。這些方法是:
- int read(byte[])
- int read(byte[], int offset, int length)
每次讀取一個字節(jié)數(shù)組顯然要比每次讀取一個字節(jié)要快的多,所以只要有可能,你可以使用這類的方法來替代read()方法。
read(byte[])方法會讀取所有數(shù)據(jù)到數(shù)組中。它會返回一個int值,來告訴實際讀取的字節(jié)數(shù)。萬一實際讀取的字節(jié)數(shù)要比提供的字節(jié)少,那么字節(jié)數(shù)組的其余部分將包含與讀取開始之前所做的相同的數(shù)據(jù)。要記住去檢查返回的int值,看實際取得的字節(jié)數(shù)有多少。
read(byte[], int offset, int length)方法也是讀數(shù)組到數(shù)組中,但是可以根據(jù)參數(shù)來規(guī)定開始的偏移量和一共讀取多少長度。返回值和read(byte[])方法的含義相同。
兩個方法相同的地方都是如果返回值是 -1 ,代表讀取結束。
下面的例子為如何使用InputStream的read(byte[])方法:
InputStream inputstream = new FileInputStream("c:\\data\\input-text.txt");
byte[] data = new byte[1024];
int bytesRead = inputstream.read(data);
while(bytesRead != -1) {
doSomethingWithData(data, bytesRead);
bytesRead = inputstream.read(data);
}
inputstream.close();
首先,上面代碼創(chuàng)建了一個字節(jié)數(shù)組。然后創(chuàng)建了一個叫bytesRead的int類型變量,去接受每次調用read(byte[])方法的返回值。
在循環(huán)里,doSomethingWithData()方法被循環(huán)調用,傳遞進去讀了多少字節(jié)和字節(jié)數(shù)組。在循環(huán)的最后把數(shù)據(jù)重新讀到數(shù)組一遍。
不用花太多精力放在研究怎么樣使用read(byte[], int offset, int length)方法來替換read(byte[])。你完全可以在任何時候用read(byte[], int offset, int length)替換掉read(byte[])方法。
mark()和reset()
InputStream類中有兩個方法mark()和reset(),但是它的子類不一定有支持(或者說子類有沒有重寫此方法)。
如果一個InputStream的子類支持這兩個方法,子類會重寫markSupported()方法并返回 true。相反的,如果返回false,則子類不支持這兩個方法。
mark()方法在InputStream設置一個內部的標記,標記在流中哪個數(shù)據(jù)到目前為止已經被讀取。使用InputStream的代碼,可以根據(jù)這個標記位來繼續(xù)讀取數(shù)據(jù)。
在讀取流的過程匯總,如果想退回到標記的那點上,可以調用reset()方法。然后InputStream退回到標記位上,開始從這個位置開始返回數(shù)據(jù)。這當然會導致多次返回一些數(shù)據(jù)
當實現(xiàn)一個解析器時,會經常用到這兩個方法。解析器讀取一個InputStream時會提前讀,如果解析器沒有找到它想要的,他可能需要回退并且將已讀數(shù)據(jù)和其他的數(shù)據(jù)進行匹配。