天天看點

Io彙總(二) inputStream 以及子類

InputStream

public abstract class InputStream implements Closeable

位元組輸入流的所有超類

abstract int read()   從輸入流讀取資料的下一個位元組。  

int read(byte[] b)    從輸入流讀取一些位元組數,并将它們存儲到緩沖區 b 。  

int read(byte[] b, int off, int len)   從輸入流讀取最多 len位元組的資料到一個位元組數組。

void close()   關閉此輸入流并釋放與流相關聯的任何系統資源。    

available()    傳回從該輸入流中可以讀取(或跳過)的位元組數的估計值,而不會被下一次調用此輸入流的方法阻塞。  

void mark(int readlimit)   标記此輸入流中的目前位置。  

boolean markSupported()    測試這個輸入流是否支援 mark和 reset方法。  

void reset()   将此流重新定位到上次在此輸入流上調用 mark方法時的位置。  

long skip(long n)   跳過并丢棄來自此輸入流的 n位元組資料。                                                                                                                       

int read(byte b[], int off, int len)      off  從byte[]的off位置開始儲存                        len  存儲多少個位元組

public int read(byte b[], int off, int len) throws IOException {
        int c = read();  //讀取一個位元組(位元組)
        if (c == -1) {   // 沒有資料 傳回-1 
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {    // 一個一個讀取 放入byte[]中
                c = read(); 
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i; // 傳回讀取了多少個位元組
    }
           

long skip(long n)   跳過并丢棄來自此輸入流的 n位元組資料       傳回  實際跳過的位元組數

public long skip(long n) throws IOException {
        long remaining = n;  //
        int nr;
        if (n <= 0) {  //
            return 0;
        } 

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
        byte[] skipBuffer = new byte[size];
        while (remaining > 0) {  //讀取位元組數
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }
        return n - remaining; //實際跳過的位元組數
    }
           

FileInputStream

class FileInputStream extends InputStream

檔案輸入流

構造函數 

public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();  //傳回null
        if (security != null) {
            security.checkRead(name);
        }
       
        if (file.isInvalid()) { // 位址是否無效
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor(); // 檔案描述類
        isFdOwner = true;
        this.path = name;

        BlockGuard.getThreadPolicy().onReadFromDisk();
        open(name);
        guard.open("close");
    }
           

int read()    b[0] & 0xff 原理

 轉化位元組碼

public int read() throws IOException {
        byte[] b = new byte[1];
        return (read(b, 0, 1) != -1) ? b[0] & 0xff : -1;
    }
           

int read(byte b[], int off, int len)

public int read(byte b[], int off, int len) throws IOException {
        if (closed && len > 0) {
            throw new IOException("Stream Closed");
        }
        tracker.trackIo(len);              
        return IoBridge.read(fd, b, off, len);  // 看不懂  擷取一個一個位元組
    }
           

擴充   硬碟的讀寫原理

盤片表面凹凸不平,凸起的地方被磁化,凹的地方是沒有被磁化;凸起的地方代表數字1(磁化為1),凹的地方代表數字0。是以硬碟可以以二進制來存儲表示文字、圖檔等資訊。

硬碟的組成

硬碟都是由盤片、磁頭、盤片主軸、控制電機、磁頭控制器、資料轉換器、接口、緩存等幾個部份組成

讀取規則 從上到下,然後從外到内。資料的讀/寫按柱面進行,而不按盤面進行。

FilterInputStream   

class FilterInputStream extends InputStream

包含一些其他輸可入流,它用作其基本的資料源,能會沿途轉換資料或提供附加功能  (裝飾者模式 中裝飾的基類)

InputStream  in  采用裝飾着模式     該類方法預設調用in 中的對應方法

protected volatile InputStream in;

 protected FilterInputStream(InputStream in) {
        this.in = in;  //
}
           

BufferedInputStream

public class BufferedInputStream extends FilterInputStream

BufferedInputStream為另一個輸入流添加了功能,即緩沖輸入和支援mark和reset方法的功能

protected byte[] buf   存儲資料的内部緩沖區數組。  

protected int count    索引一大于緩沖區中最後一個有效位元組的索引。  

protected int marklimit   mark方法調用後,最大超前允許,後續調用 reset方法失敗。  

protected int markpos    pos字段在最後一個 mark方法被調用時的值。  

protected int pos  緩沖區中的目前位置。

protected volatile byte buf[]; // 位元組緩存數組
protected int count;        //位元組的數量
protected int pos;          // 下一位元組讀取的下标
protected int markpos = -1; //标記位置下标
protected int marklimit;    //标記上限
           

synchronized int read()

public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }
           

 fill()    

private void fill() throws IOException {
        byte[] buffer = getBufIfOpen(); 
        if (markpos < 0) // 沒有标記
            pos = 0;           
        else if (pos >= buffer.length) 
            if (markpos > 0) {  // 有标記
                int sz = pos - markpos; // 從
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                pos = sz;
                markpos = 0;
            } else if (buffer.length >= marklimit) {
                markpos = -1;   /* buffer got too big, invalidate mark */
                pos = 0;        /* drop buffer contents */
            } else if (buffer.length >= MAX_BUFFER_SIZE) {
                throw new OutOfMemoryError("Required array size too large");
            } else {    //
                int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
                        pos * 2 : MAX_BUFFER_SIZE;
                if (nsz > marklimit)
                    nsz = marklimit;
                byte nbuf[] = new byte[nsz];
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                buffer = nbuf;
            }
        count = pos;
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        if (n > 0)
            count = n + pos;
    }
           

synchronized int read(byte b[], int off, int len)

public synchronized int read(byte b[], int off, int len)
        throws IOException
    {
        ...  檢測資料
        int n = 0;
        for (;;) {
            int nread = read1(b, off + n, len - n);
            if (nread <= 0)
                return (n == 0) ? nread : n;
            n += nread;
            if (n >= len)
                return n;
            InputStream input = in;
            if (input != null && input.available() <= 0)
                return n;
        }
    }
           

int read1(byte[] b, int off, int len) 

如果緩沖區有資料就從緩沖區讀取 如果沒有就調用fill 從流中讀取

private int read1(byte[] b, int off, int len) throws IOException {
        int avail = count - pos;
        if (avail <= 0) {
            if (len >= getBufIfOpen().length && markpos < 0) {
                return getInIfOpen().read(b, off, len);
            }
            fill();
            avail = count - pos;
            if (avail <= 0) return -1;
        }
        int cnt = (avail < len) ? avail : len;
        System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
        pos += cnt;
        return cnt;
    }
           

ByteArrayInputStream

class ByteArrayInputStream extends InputStream 

ByteArrayInputStream包含一個内部緩沖區,其中包含可以從流中讀取的位元組

protected byte[] buf   由資料流的建立者提供的位元組數組。  

protected int count   索引一大于輸入流緩沖區中的最後一個有效字元。  

protected int mark   流中目前标記的位置。  

protected int pos   從輸入流緩沖區讀取的下一個字元的索引。  

public synchronized int read()

public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }
           

 synchronized int read(byte b[], int off, int len)

public synchronized int read(byte b[], int off, int len) {
        if (pos >= count) {
            return -1;
        }
        int avail = count - pos;
        if (len > avail) {
            len = avail;
        }
        if (len <= 0) { return 0; }
        System.arraycopy(buf, pos, b, off, len); //從本身buf裡面的資料拷貝到讀取的位元組數組中
        pos += len;
        return len;
    }
           

DataInputStream

class DataInputStream extends FilterInputStream implements DataInput

資料輸入流允許應用程式以獨立于機器的方式從底層輸入流讀取原始Java資料類型  ()

int read(byte[] b)   從包含的輸入流中讀取一些位元組數,并将它們存儲到緩沖區數組 b 。  

int read(byte[] b, int off, int len)   從包含的輸入流讀取最多 len個位元組的資料為位元組數組。  

boolean readBoolean()   見的總承包 readBoolean的方法 DataInput 。  

byte readByte()  見的總承包 readByte的方法 DataInput 。  

char readChar()  見 readChar方法的總合同 DataInput 。  

double readDouble()  見 readDouble方法 DataInput的總體合同。  

float readFloat()  見 readFloat法 DataInput的一般合同。  

void readFully(byte[] b)  見的總承包 readFully的方法 DataInput 。  

void readFully(byte[] b, int off, int len)   見的總承包 readFully的方法 DataInput 。  

int readInt()  見 readInt方法 DataInput的一般合同。  

long readLong()  見的總承包 readLong的方法 DataInput 。  

short readShort()  見 readShort方法 DataInput的一般合同。  

int readUnsignedByte()  見的總承包 readUnsignedByte的方法 DataInput 。  

int readUnsignedShort()  見 readUnsignedShort法 DataInput的一般合同。  

String readUTF()  見 readUTF法 DataInput的一般合同。  

static String readUTF(DataInput in)  從流in讀取以modified UTF-8格式編碼的Unicode字元串的表示; 這個字元串然後作為String傳回。  

int skipBytes(int n)  見 skipBytes法 DataInput的一般合同。  

final int read(byte b[])

public final int read(byte b[]) throws IOException {
        return in.read(b, 0, b.length);
    }
           

final int read(byte b[], int off, int len)

public final int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }
           

final int readInt()

public final int readInt() throws IOException {
        // b/30268192
        // Android-changed: Use read(byte[], int, int) instead of read().
        readFully(readBuffer, 0, 4);
        return Memory.peekInt(readBuffer, 0, ByteOrder.BIG_ENDIAN);
    }
           

final void readFully(byte b[], int off, int len)

public final void readFully(byte b[], int off, int len) throws IOException {
        if (len < 0)
            throw new IndexOutOfBoundsException();
        int n = 0;
        while (n < len) {
            int count = in.read(b, off + n, len - n);
            if (count < 0)
                throw new EOFException();
            n += count;
        }
    }
           

final boolean readBoolean()

public final boolean readBoolean() throws IOException {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        return (ch != 0);
    }
           

final byte readByte()

public final byte readByte() throws IOException {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        return (byte)(ch);
    }