Java8 I/O源码-DataInputStream与DataOutputStream

前面已经学习了FilterInputStream与FilterOutputStream。文章中到了FilterInputStream与FilterOutputStream的子类可进一步重写父类方法中的一些方法,来提供装饰功能。今天就来介绍下它们子类中的DataInputStream与DataOutputStream。

DataInputStream为数据输入流,它允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。
DataOutputStream为数据输出流,它允许应用程序以适当方式将基本 Java数据类型写入输出流中。

阅读源码需要复习一些基础知识,比如基本数据类型、位移运算、&xFF操作。

先来复习下基本数据类型各有多少位。

基本数据类型 byte short int long float double boolean char
8 16 32 64 32 64 1 16


再来复习下位移运算符中的<<和>>>

<<表示左移运算符,是将运算符左边的对象,向左移动运算符右边指定的位数,并且在低位补零。其实,向左移n 位,就相当于乘上2 的n 次方。

如,20 < 2;20的二进制为 0001 0100,右移2位后为 0010 1000,则结果就为 40;

>>>表示无符号右移,也叫逻辑右移。即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。

如,20 >>> 2;20的二进制为 0001 0100,右移2位后为 0000 0101,则结果就为 5;
而-20 >> 2;-20的二进制为 1110 1011,右移2位,此时高位补0,即 0011 1010,结果为58;

最后复习下&xFF操作代表什么含义。

取低8位。0xFF是二进制的 1111 1111,那么0000 1010 0101 0101&1111 1111就能取到0000 1010 0101 0101的低8位。

DataInputStream

下面来看下DataInputStream的源码。

/**
 * DataInput接口用于从二进制流中读取字节,并根据所有Java基本类型数据进行重构。
 * 同时还提供根据UTF-8修改版格式的数据重构String的工具。
 */
public class DataInputStream extends FilterInputStream implements DataInput {
   
   

    /**
     * 构造方法之一
     * 使用特定的输出流创建DataInputStream
     */
    public DataInputStream(InputStream in) {
        super(in);
    }

    /**
     * readUTF()使用的数组
     */
    private byte bytearr[] = new byte[80];
    private char chararr[] = new char[80];

    /**
     * 从输入流中读取b.length个数据保存到byte数组b中。
     * 实际读取的字节数以整数的形式返回。
     * 在输入数据可用、检测到文件末尾、或抛出异常之前,该方法一直阻塞。
     * 如果b为null,会抛出NullPointerException。
     * 如果b长度为0,不会读取数据,方法返回值为0;否则会尝试读取至少一个字节。
     * 如果因为流在文件末尾导致没有字节可用,将返回-1;否则至少会读取一个字节并保存到b中。
     *
     * 第一个字节保存到b[0],下一个字节保存到b[1],以此类推。
     * 读取的字节数最大等于b的长度。
     *
     * 此方法等价于read(b, 0, b.length)
     *
     * @param      b   存储读取数据的byte数组
     * @return     实际读取的字节数, 如果因为到达流末尾导致没有数据,返回-1。
     * @exception  IOException 如果不是因为流位于文件末尾而无法读取第一个字节;该流已关闭并且底层输入流在关闭后不支持读取操作;发生其他 I/O错误。
     */
    public final int read(byte b[]) throws IOException {
        return in.read(b, 0, b.length);
    }

    /**
     * 从包含的输入流中将最多len个字节读入一个byte数组中。
     * 尽量读取len个字节,但读取的字节数可能少于len个,也可能为零。
     * 以整数形式返回实际读取的字节数。
     * 在输入数据可用、检测到文件末尾或抛出异常之前,此方法将阻塞。
     * 
     * 如果len为零,则不读取任何字节并返回0;
     * 否则,尝试读取至少一个字节。如果因为流位于文件未尾而没有字节可用,则返回值-1;
     * 否则,至少读取一个字节并将其存储到b中。
     *
     * @param      b     存储读取数据的缓冲区。
     * @param off  目标数组 b 中的起始偏移量
     * @param      len   读取的最大字节数。
     * @return     读入缓冲区的字节总数;如果因为已经到达流末尾而没有更多的数据,则返回-1。
     * @exception  NullPointerException 如果b为null。
     * @exception  IndexOutOfBoundsException  如果off为负, len为负,或者len大于b.length-off
     * @exception  IOException 如果不是因为流位于文件末尾而无法读取第一个字节;该流已关闭并且底层输入流在关闭后不支持读取操作;发生其他I/O 
     */
    public final int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }

    /**
     * 参考DataInput.readFully()的介绍。
     * 
     * 以下是DataInput.readFully()的介绍。
     * 从输入流中读取一些字节,并将它们存储在缓冲区数组b中。读取的字节数等于b的长度。
     * 
     * 该方法的执行结果有三种:
     * 1.输入数据的 len 个字节是可用的,在这种情况下,正常返回。
     * 2.检测到文件末尾,在这种情况下,抛出 EOFException。
     * 3.如果发生 I/O 错误,在这种情况下,将抛出 IOException,而不是 EOFException。
     * 
     * 如果b为null,则抛出NullPointerException。
     * 如果off为负,或len为负,或者off+len大于数组b的长度,则抛出IndexOutOfBoundsException。
     * 如果len为零,则不读取字节。
     * 否则,将读取的第一个字节存储到元素b[off]中,下一个字节存储到 b[off+1]中,
     * 依此类推。读取的字节数至多等于b[0]。
     * 
     * @param      b  存储读取数据的缓冲区。
     * @exception  EOFException  如果此输入流在读取所有字节之前到达末尾。
     * @exception  IOException   该流已关闭并且包含的输入流在关闭后不支持读取操作,或者发生其他 I/O 错误。
     */
    public final void readFully(byte b[]) throws IOException {
        readFully(b, 0, b.length);
    }

    /**
     * 参考readFully(byte b[])
     *
     * @param      b     存储读取数据的缓冲区。
     * @param      off   指定数据中的偏移量
     * @param      len   指定读取的字节数
     * @exception  EOFException  如果此流在读取所有字节之前到达末尾。
     * @exception  IOException 该流已关闭并且包含的输入流在关闭后不支持读取操作,或者发生其他I/O错误。
     */
    public final void readFully(byte b[], int off, int len) throws IOException {
        //如果参数不合法,抛出异常
        if (len < 0)
            throw new IndexOutOfBoundsException();
        int n = 0;
        //读取字节,直到读取了len个字节
        while (n < len) {
            int count = in.read(b, off + n, len - n);
            
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值