byte
了解InputStream前,我們先了解下byte.
- byte存在的意義:
byte,字節,java中一種基本類型.通常在讀取非文本文件(圖片,聲音,可執行文件,網絡通信的數據)需要通過字節數組來保存文件中的內容.
一個byte占用了8個bit位,所以byte的取值范圍為-128到127.
內存的最小單元是字節,Intel的X86的芯片內存地址是通過字節編的,指針可以指向的最小內存單元就是一個字節,16位的機器是兩個字節,32位的機器是四個字節. - byte的包裝類
byte的包裝類就是Byte,列舉一下常見方法
- toString(byte b) //靜態的,調用了Integer.toString()
- ByteCache() //不是很懂,也不是靜態方法啊
- parseByte(String s) //超過范圍或者不是數字會報:NumberFormatException,調用了Integer.parseInt()
- valueOf() //把括號里的參數變成Byte對象,超過范圍或者不是數字會報:NumberFormatException
- byteValue() //返回Byte里的byte
- shortValue() //返回short,代碼里加了強轉,平時不寫是隱式類型轉換,jvm實現的。
- intValue(),longValue() //同上
- floatValue(),doubleValue() //同上,但是不知道精度是否會丟失【TODO】
- toString() //源碼里調用了Integer.toString,非靜態
- hashCode() //返回這個類的hashCode
- equals() //直接比byte了,也不用比hashCode了
- compareTo(Byte anotherByte) //和另外一個Byte比較大小
- compare(byte x, byte y) //靜態方法
InputStream
抽象架構圖
InputSteam是所有字節輸入流的實現類的基類.它封裝了流處理類的基本操作.
緩存區字節數組最大值
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
從輸入流中讀取數據的下一個字節,返回int
public abstract int read() throws IOException;
從輸入流中讀取b.length大小的字節,并存儲到字節數組b.
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
該方法調用了抽象方法:read(),通過該方法獲取流中下一個元素.
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException e) {
}
return i;
}
原始流處理器
接收一個Byte數組對象,或者一個FileDiscriptor對象,一個String對象,或者其他類型的流源對象.
主要一下四種:
ByteArrayInputStream
- ByteArrayInputStream里的方法基本上都被synchronized關鍵字修飾,所以它是線程安全的.
- ByteArrayInputStream底層是一個緩沖字節數組
/**
* An array of bytes that was provided
* by the creator of the stream. Elements <code>buf[0]</code>
* through <code>buf[count-1]</code> are the
* only bytes that can ever be read from the
* stream; element <code>buf[pos]</code> is
* the next byte to be read.
*/
protected byte buf[];
- 一般情況下很少使用ByteArrayInputStream,它存在的意義一方面是擴展了InputStream基類,可以通過它賴操作字節數組,另一方面,相當于是其他所有流的一個中間狀態.,用來緩存其他流輸入的數據.
- 關閉一個字節流是沒有意義的.
/**
* Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
*/
public void close() throws IOException {
}
FileInputStream
先了解下一些相關類的實現:JDK源碼-File系列
- FileInputStream用來操作文件流數據,通過構造函數可知,可以通過文件路徑,文件對象,文件描述符對象來創建文件輸入流對象.
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
public FileInputStream(File file) throws FileNotFoundException {
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor();
fd.attach(this);
path = name;
open(name);
}
public FileInputStream(FileDescriptor fdObj) {
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
throw new NullPointerException();
}
if (security != null) {
security.checkRead(fdObj);
}
fd = fdObj;
path = null;
/*
* FileDescriptor is being shared by streams.
* Register this stream with FileDescriptor tracker.
*/
fd.attach(this);
}
- FileInputStream的讀取操作和打開文件的操作都是調用本地的native方法.
/**
* Opens the specified file for reading.
* @param name the name of the file
*/
private native void open0(String name) throws FileNotFoundException;
// wrap native call to allow instrumentation
/**
* Opens the specified file for reading.
* @param name the name of the file
*/
private void open(String name) throws FileNotFoundException {
open0(name);
}
/**
* Reads a byte of data from this input stream. This method blocks
* if no input is yet available.
*
* @return the next byte of data, or <code>-1</code> if the end of the
* file is reached.
* @exception IOException if an I/O error occurs.
*/
public int read() throws IOException {
return read0();
}
private native int read0() throws IOException;
PipedInputStream&PipedOutputStream
PipedInputStream與PipedOutputStream的設計,主要為了實現線程之間可以通過字節流來傳輸數據,來達到通信.
參考文章:Java流編程實例及代碼
StringBufferInputStream
StringBufferInputStream:將一個字符串緩沖區轉換為一個輸入流。接收一個String對象作為流的源。(JDK幫助文檔上說明:已過時。此類未能正確地將字符轉換為字節。從JDK1.1開始,從字符串創建流的首選方法是通過StringReader類進行創建。只有字符串中每個字符的低八位可以由此類使用。)
ObjectInputStream/ObjectOutputStream
詳見JDK源碼-InputStream系列之ObjectOutputStream/ObjectInputStream
鏈接流處理器
FilterInputStream
- FilterInputStream主要用于包裝一些其他的基本數據的流對象.
- 該類以及父類,子類的設計對應了裝飾者模式.通過FilterInputStream的代理,所有的子類都可以裝飾一個InputStream類型的對象.這樣,就能夠實現所有裝飾類之間的互相轉換了.
- FilterInputStream實現了InputStream接口,同樣實現了流處理對象的那一套方法.
BufferedInputStream
- 它存在的意義是給另外的輸入流添加功能,例如,提供“緩沖功能”以及支持“mark()標記”和“reset()重置方法”。
- 它的底層實現是一個內部緩存數組.在讀取輸入流的時候,它會分批讀入到緩沖區,當緩沖區中的數據被讀完之后,輸入流會再次填充數據緩沖區.