特殊流/数据流(DataInputStream与DataOutputStream)分析

本文分析了Java中的特殊流DataInputStream和DataOutputStream,它们属于高级字节流,用于以平台无关的方式读写基本数据类型。DataInputStream提供readUTF等特有方法,而DataOutputStream包含各种数据的写入方法。文章探讨了它们的继承结构和不同读写方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

特殊流(DataInputStream与DataOutputStream)分析

特殊流/数据流(DataInputStream与DataOutputStream)引用的是字节流,所以DataInputStream与DataOutputStream属于高级流。

DataInputStream

数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。应用程序可以使用数据输出流写入稍后有数据输入流读取的数据。DateInputStream对于多线程访问不一定是安全的。线程安全是可选的,它由此类方法的使用者负责。

**

源码分析

**
继承关系
class DataInputStream extends FilterInputStream implements
第一种读取方式,无参

 /**
     /* int read() throws IOException {
         return in.read()
     /*读取第一个字节,返回值为int类型(使用FilterInputStream中的read()方法)
     */
     System.out.println(dataInputStream.read());

第二种读取方式,参数为byte[]

/**
             * final int read(byte b[]) throws IOException {
             *              return in.read(b, 0, b.length);
             *              }
             *  返回值为int类型,返回结果为读取到的实际个数
             */

            byte [] b=new byte[30];
            System.out.println(dataInputStream.read(b));
            System.out.println(Arrays.toString(b));

第三种读取方式,有参

/**
             *final int read(byte b[], int off, int len) throws IOException {
             *         return in.read(b, off, len);
             *  返回值:int类型,实际读取到的个数
             *  参数:
             *  byte b[]:表示读取到的数据存储到该数组
             *  int off:表示从存储数组的偏移位置off开始存储字符
             *  int len:读取的数据的长度
             */
            byte [] b=new byte[30];

            System.out.println(dataInputStream.read(b,0,5));
            System.out.println(Arrays.toString(b));

特有方法
readUTF读取由writeUTF修改的数据。

/**
             * 特殊方法
             * final String readUTF() throws IOException {
             *    return readUTF(this);
             */
            System.out.println(dataInputStream.readUTF());
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);
    }
}

其他方法



    public abstract void readFully(byte abyte0[])
        throws IOException;

    public abstract void readFully(byte abyte0[], int i, int j)
        throws IOException;

    public abstract int skipBytes(int i)
        throws IOException;

    public abstract boolean readBoolean()
        throws IOException;

    public abstract byte readByte()
        throws IOException;

    public abstract int readUnsignedByte()
        throws IOException;

    public abstract short readShort()
        throws IOException;

    public abstract int readUnsignedShort()
        throws IOException;

    public abstract char readChar()
        throws IOException;

    public abstract int readInt()
        throws IOException;

    public abstract long readLong()
        throws IOException;

    public abstract float readFloat()
        throws IOException;

    public abstract double readDouble()
        throws IOException;

DataOutputStream

源码分析
继承关系

class DataOutputStream extends FilterOutputStream implements DataOutput {
第一种写入方法,写入单个字节

/**
 * synchronized void write(int b) throws IOException {
 *         out.write(b);
 *         incCount(1);
 *         写入一个字节
 */
            dataOutputStream.write(97);

第二种写入方法,写入

  /**
   * synchronized void write(byte b[], int off, int len)
   *         throws IOException
   *     {
   *         out.write(b, off, len);
   *         incCount(len);
   *     }
   */
            byte[] b=new byte[]{97,98,99,103,113,107,100,112,108};
            dataOutputStream.write(b,0,5);

第三种写入方法(特殊写入方法)

/**
 * final void writeUTF(String str) throws IOException {
 *         writeUTF(str, this);
 *     }
 */
 dataOutputStream.writeUTF("11.24你好tulun");

该写入方法写入的数据只能通过readUTF读取。

static int writeUTF(String str, DataOutput out) throws IOException {
        int strlen = str.length();
        int utflen = 0;
        int c, count = 0;

        /* use charAt instead of copying String to char array */
        for (int i = 0; i < strlen; i++) {
            c = str.charAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) {
                utflen++;
            } else if (c > 0x07FF) {
                utflen += 3;
            } else {
                utflen += 2;
            }
        }

        if (utflen > 65535)
            throw new UTFDataFormatException(
                "encoded string too long: " + utflen + " bytes");

        byte[] bytearr = null;
        if (out instanceof DataOutputStream) {
            DataOutputStream dos = (DataOutputStream)out;
            if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
                dos.bytearr = new byte[(utflen*2) + 2];
            bytearr = dos.bytearr;
        } else {
            bytearr = new byte[utflen+2];
        }

        bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
        bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);

        int i=0;
        for (i=0; i<strlen; i++) {
           c = str.charAt(i);
           if (!((c >= 0x0001) && (c <= 0x007F))) break;
           bytearr[count++] = (byte) c;
        }

        for (;i < strlen; i++){
            c = str.charAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) {
                bytearr[count++] = (byte) c;

            } else if (c > 0x07FF) {
                bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
                bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
                bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
            } else {
                bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
                bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
            }
        }
        out.write(bytearr, 0, utflen+2);
        return utflen + 2;
    }

其他方法:同DataInputStream拥有基本类型的 写入方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值