JavaIO-DataInputStream源码分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nimasike/article/details/89066549
package java.io;

public class DataInputStream extends FilterInputStream implements DataInput {


	//传入底层输入流
    public DataInputStream(InputStream in) {
        super(in);
    }

    //字节缓冲区
    private byte bytearr[] = new byte[80];
	//字符缓冲区
    private char chararr[] = new char[80];

    
	//从底层流中读取字节到缓冲区b,返回值是已经读了多少了字节
    public final int read(byte b[]) throws IOException {
        return in.read(b, 0, b.length);
    }

    //从底层流中读取字节放入缓冲区b中,off是b的起始位置,len是最多读取多少个字节,返回值表示实际读取了多少字节
    public final int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }

    //从底层流中读取子节到缓冲区b中,如果一次读取没把b填充满,则循环继续读到满为止。
    public final void readFully(byte b[]) throws IOException {
        readFully(b, 0, b.length);
    }

    
    public final void readFully(byte b[], int off, int len) throws IOException {
        if (len < 0)
            throw new IndexOutOfBoundsException();
		//n记录一共读取了多少个字节
        int n = 0;
		//N < len 说明没读满,一直读到len个字节为止
        while (n < len) {
		    //从底层流中读取字节
            int count = in.read(b, off + n, len - n);
            if (count < 0)
                throw new EOFException();
			//叠加读取的字节数
            n += count;
        }
    }

    //跳过N个字节
    public final int skipBytes(int n) throws IOException {
        int total = 0;
        int cur = 0;
		
		//如果1次没有跳过N个字节,则循环执行skip一直到跳过N个字节为止
        while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) {
            total += cur;
        }

        return total;
    }

    //读取一个字节,1:true 0:false
    public final boolean readBoolean() throws IOException {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        return (ch != 0);
    }

    //读取一个字节,有符号,如果字节为11111111,以byte类型返回则值为-1
    public final byte readByte() throws IOException {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        return (byte)(ch);
    }

    //读取一个字节,无符号,如果字节为11111111,以int类型返回则值为255
    public final int readUnsignedByte() throws IOException {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        return ch;
    }

    //读取俩个字节,转换为short,有符号
    public final short readShort() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (short)((ch1 << 8) + (ch2 << 0));
    }

	//读取俩个字节,转换为int,无符号
    public final int readUnsignedShort() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (ch1 << 8) + (ch2 << 0);
    }

	//读取俩个字节,转换为unncode码点返回
    public final char readChar() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (char)((ch1 << 8) + (ch2 << 0));
    }

    //读取4个字节,移位后转换为int
    public final int readInt() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        int ch3 = in.read();
        int ch4 = in.read();
        if ((ch1 | ch2 | ch3 | ch4) < 0)
            throw new EOFException();
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    }

    private byte readBuffer[] = new byte[8];

   //读取8个字节,移位后转换为long
    public final long readLong() throws IOException {
        readFully(readBuffer, 0, 8);
        return (((long)readBuffer[0] << 56) +
                ((long)(readBuffer[1] & 255) << 48) +
                ((long)(readBuffer[2] & 255) << 40) +
                ((long)(readBuffer[3] & 255) << 32) +
                ((long)(readBuffer[4] & 255) << 24) +
                ((readBuffer[5] & 255) << 16) +
                ((readBuffer[6] & 255) <<  8) +
                ((readBuffer[7] & 255) <<  0));
    }

    //读取4个字节(int),将int的二进制转换为float
    public final float readFloat() throws IOException {
        return Float.intBitsToFloat(readInt());
    }

   //读取8个字节(long),将long的二进制转换为double
    public final double readDouble() throws IOException {
        return Double.longBitsToDouble(readLong());
    }

    private char lineBuffer[];

    
	//读取字节转换为utf-8
    public final String readUTF() throws IOException {
        return readUTF(this);
    }

    //读取字节转换为utf-8
    public final static String readUTF(DataInput in) throws IOException {
		//先读取俩个字节,无符号,得到的值是utf-8编码的字节长度
        int utflen = in.readUnsignedShort();
		
		//字节和字符缓冲区
        byte[] bytearr = null;
        char[] chararr = null;
		
		//判断容量,不够就扩容
        if (in instanceof DataInputStream) {
            DataInputStream dis = (DataInputStream)in;
            if (dis.bytearr.length < utflen){
                dis.bytearr = new byte[utflen*2];
                dis.chararr = new char[utflen*2];
            }
            chararr = dis.chararr;
            bytearr = dis.bytearr;
        } else {
            bytearr = new byte[utflen];
            chararr = new char[utflen];
        }
		
		//字符变量
        int c, char2, char3;
        int count = 0;
        int chararr_count=0;
			
		//把utf-8字节全部读入到bytearr当中
        in.readFully(bytearr, 0, utflen);

		//循环
        while (count < utflen) {
			//读取一个字节&11111111
            c = (int) bytearr[count] & 0xff;
			//如果>127则退出循环
            if (c > 127) break;
            count++;
			//127以内直接转换为unicode码点
            chararr[chararr_count++]=(char)c;
        }
		
		//循环
        while (count < utflen) {
			//读取一个字节&11111111
            c = (int) bytearr[count] & 0xff;
			//右移4位,如果值为0-7,说明字节的值为0xxxxxxx,所以右移4位=0000 0xxx,所以值肯定是1-7.
			//直接把当前字节转换为unicode码点
            switch (c >> 4) {
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                    /* 0xxxxxxx*/
                    count++;
                    chararr[chararr_count++]=(char)c;
                    break;
					
				//右移4位,如果是已110x xxxx开头的utf-8,所以右移4位= 0000 110x,所以值肯定是12或13.
				//说明2个字节表示一个unicode码点。
                case 12: case 13:
                    /* 110x xxxx   10xx xxxx*/
					//所以count+2,表示这次处理了2个字节
                    count += 2;
                    if (count > utflen)
                        throw new UTFDataFormatException(
                            "malformed input: partial character at end");
							
					//在读取一个字节.
                    char2 = (int) bytearr[count-1];
					
					//char2 & 11000000  != 10000000 说明这个字节不是10xxxxxx模式的。
                    if ((char2 & 0xC0) != 0x80)
                        throw new UTFDataFormatException(
                            "malformed input around byte " + count);
							
					//c & 0x1F(00011111) << 6 = 00000xxx xx000000
					//char2 & 0x3F(00111111) = 00xxxxxx
					//00000xxx xx000000 | 00xxxxxx = 00000xxx, xxxxxxxx
					//转换为unicode码点
                    chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
                                                    (char2 & 0x3F));
                    break;
                case 14:
					//原理同上
                    /* 1110 xxxx  10xx xxxx  10xx xxxx */
                    count += 3;
                    if (count > utflen)
                        throw new UTFDataFormatException(
                            "malformed input: partial character at end");
                    char2 = (int) bytearr[count-2];
                    char3 = (int) bytearr[count-1];
                    if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
                        throw new UTFDataFormatException(
                            "malformed input around byte " + (count-1));
                    chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |
                                                    ((char2 & 0x3F) << 6)  |
                                                    ((char3 & 0x3F) << 0));
                    break;
                default:
                    /* 10xx xxxx,  1111 xxxx */
                    throw new UTFDataFormatException(
                        "malformed input around byte " + count);
            }
        }
        // The number of chars produced may be less than utflen
        return new String(chararr, 0, chararr_count);
    }
}

猜你喜欢

转载自blog.csdn.net/nimasike/article/details/89066549