Java中IO框架——DataInputStream源码解析

DataInputStream 继承了 FilterInputStream 类,同时实现了 DataInput 接口。
DataInput 接口提供了一些方法,而在 DataInputStream 中对这些方法进行了实现。

直接来看 DataInputStream 的源码即可。

属性

从父类 FilterInputStream 继承的流对象 in 。

构造函数

使用指定的底层 InputStream 创建一个 DataInputStream。

    public DataInputStream(InputStream in) {
        super(in);
    }

方法

read(byte b[])

    // 调用输入流自己的read方法,本类未进行修饰
    // 从输入流中读取一定数量的字节,放于字节数组b中,从0下标位置开始存放,最多将b数组存满
    public final int read(byte b[]) throws IOException {
        return in.read(b, 0, b.length);
    }

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

    // 调用了输入流自己的read方法,本类未进行修饰
    public final int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }

readFully

从输入流中读取一些字节,并将它们存储在缓冲区数组 b 中。读取的字节数等于 b 的长度。在出现以下条件之一以前,此方法将一直阻塞:
- 输入数据的 b.length 个字节是可用的,在这种情况下,正常返回。
- 检测到文件末尾,在这种情况下,抛出 EOFException。
- 发生 I/O 错误,在这种情况下,将抛出 IOException,而不是 EOFException。

    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 {
        // 如果需要读取的个数len小于0,抛出范围异常
        if (len < 0)
            throw new IndexOutOfBoundsException();
        // 定义累加计数的n
        int n = 0;
        // n小于目标个数就继续循环读取,直到n=len为止
        while (n < len) {
            // 调用输入流自身的read方法来进行读取,直到读够对应的字节数
            int count = in.read(b, off + n, len - n);
            if (count < 0)
                // 读不到字节了,抛出EOF异常
                throw new EOFException();
            // 累加
            n += count;
        }
    }

skipBytes(int n)

试图在输入流中跳过数据的 n 个字节,并丢弃跳过的字节。不过,可以跳过更少的字节数,该字节数甚至可以为零。这可能由很多情况引起;在已经跳过 n 个字节前到达文件末尾只是其中的一种可能。此方法从不抛出 EOFException。返回实际跳过的字节数。

    public final int skipBytes(int n) throws IOException {
        int total = 0;
        int cur = 0;

        while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) {
            total += cur;
        }

        return total;
    }

readBoolean()

读取一个输入字节,如果该字节不是零,则返回 true,如果是零,则返回 false。此方法适用于读取用接口 DataOutput 的 writeBoolean 方法写入的字节。

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

readByte()

读取并返回一个输入字节。该字节被看作是 -128 到 127(包含)范围内的一个有符号值。此方法适用于读取用接口 DataOutput 的 writeByte 方法写入的字节。

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

readUnsignedByte()

读取一个输入字节,将它左侧补零 (zero-extend) 转变为 int 类型,并返回结果,所以结果的范围是 0 到 255。如果接口 DataOutput 的 writeByte 方法的参数是 0 到 255 之间的值,则此方法适用于读取用 writeByte 写入的字节。

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

readShort()

读取两个输入字节并返回一个 short 值。设 a 为第一个读取字节, b 为第二个读取字节。此方法适用于读取用接口 DataOutput 的 writeShort 方法写入的字节。

    public final short readShort() throws IOException {
        // ch1为第一个字节,ch2为第二个字节
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        // 高位左移8位和低位8位相加
        return (short)((ch1 << 8) + (ch2 << 0));
    }

readUnsignedShort()

读取两个输入字节,并返回 0 到 65535 范围内的一个 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);
    }

readChar()

读取两个输入字节并返回一个 char 值。

    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));
    }

readInt()

读取四个输入字节并返回一个 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));
    }

readLong()

读取八个输入字节并返回一个 long 值。

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

    public final long readLong() throws IOException {
        // 读取完整的8个字节
        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));
    }

readFloat()

读取四个输入字节并返回一个 float 值。实现这一点的方法是:先使用与 readInt 方法完全相同的方式构造一个 int 值,然后使用与 Float.intBitsToFloat 方法完全相同的方式将此 int 值转换成一个 float 值。

    public final float readFloat() throws IOException {
        return Float.intBitsToFloat(readInt());
    }

readDouble()

读取八个输入字节并返回一个 double 值。实现这一点的方法是:先使用与 readlong 方法完全相同的方式构造一个 long 值,然后使用与 Double.longBitsToDouble 方法完全相同的方式将此 long 值转换成一个 double 值。

    public final double readDouble() throws IOException {
        return Double.longBitsToDouble(readLong());
    }

readUTF

读入一个已使用 UTF-8 修改版格式编码的字符串。

    public final String readUTF() throws IOException {
        return readUTF(this);
    }
   public final static String readUTF(DataInput in) throws IOException {
        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;

        in.readFully(bytearr, 0, utflen);

        while (count < utflen) {
            c = (int) bytearr[count] & 0xff;
            if (c > 127) break;
            count++;
            chararr[chararr_count++]=(char)c;
        }

        while (count < utflen) {
            c = (int) bytearr[count] & 0xff;
            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;
                case 12: case 13:
                    /* 110x xxxx   10xx xxxx*/
                    count += 2;
                    if (count > utflen)
                        throw new UTFDataFormatException(
                            "malformed input: partial character at end");
                    char2 = (int) bytearr[count-1];
                    if ((char2 & 0xC0) != 0x80)
                        throw new UTFDataFormatException(
                            "malformed input around byte " + count);
                    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);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值