当前位置:天才代写 > tutorial > JAVA 教程 > java io进修(十三) 数据输入流的认知、源码和示例

java io进修(十三) 数据输入流的认知、源码和示例

2017-11-02 08:00 星期四 所属: JAVA 教程 浏览:50

副标题#e#

DataInputStream(数据输入流)的认知、源码和示例

DataInputStream 先容

DataInputStream 是数据输入流。它担任于FilterInputStream。

DataInputStream 是用来装饰其它输入流,它“答允应用措施以与呆板无关方法从底层输入流中读取根基 Java 数据范例”。应用措施可以利用DataOutputStream(数据输出流)写入由DataInputStream(数据输入流)读取的数据。

DataInputStream 函数列表

DataInputStream(InputStream in)
final int     read(byte[] buffer, int offset, int length)
final int     read(byte[] buffer)
final boolean     readBoolean()
final byte     readByte()
final char     readChar()
final double     readDouble()
final float     readFloat()
final void     readFully(byte[] dst)
final void     readFully(byte[] dst, int offset, int byteCount)
final int     readInt()
final String     readLine()
final long     readLong()
final short     readShort()
final static String     readUTF(DataInput in)
final String     readUTF()
final int     readUnsignedByte()
final int     readUnsignedShort()
final int     skipBytes(int count)

DataInputStream.java源码阐明(基于jdk1.7.40)

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];
     
    // 从“数据输入流”中读取一个字节
    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则一直读取,直到填满位置。
    // 从字节数组b的位置0开始存储,而且读取的字节个数便是b的长度。
    public final void readFully(byte b[]) throws IOException {
        readFully(b, 0, b.length);
    }
     
    // 从“数据输入流”中读取数据并存储到字节数组b中;若没读取len个字节,直到一直读取直到读取完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;
        }
    }
     
    // 跳过n个字节
    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;
    }
     
    // 从“数据输入流”中读取boolean范例的值
    public final boolean readBoolean() throws IOException {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        return (ch != 0);
    }
     
    // 从“数据输入流”中读取Byte范例的值
    public final byte readByte() throws IOException {
        int ch = in.read();
        if (ch < 0)
            throw new EOFException();
        return (byte)(ch);
    }
     
    // 从“数据输入流”中读取“无标记的Byte范例”的值,即读取值为正数的byte值
    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));
    }
     
    // 从“数据输入流”中读取“无标记的short范例”的值
    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);
    }
     
    // 从“数据输入流”中读取“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));
    }
     
    // 从“数据输入流”中读取“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];
     
    // 从“数据输入流”中读取“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));
    }
     
    // 从“数据输入流”中读取“float范例”的值
    public final float readFloat() throws IOException {
        return Float.intBitsToFloat(readInt());
    }
     
    // 从“数据输入流”中读取“double范例”的值
    public final double readDouble() throws IOException {
        return Double.longBitsToDouble(readLong());
    }
     
    private char lineBuffer[];
     
    @Deprecated
    public final String readLine() throws IOException {
        char buf[] = lineBuffer;
     
        if (buf == null) {
            buf = lineBuffer = new char[128];
        }
     
        int room = buf.length;
        int offset = 0;
        int c;
     
loop:   while (true) {
            switch (c = in.read()) {
              case -1:
              case '\n':
                break loop;
     
              case '\r':
                int c2 = in.read();
                if ((c2 != '\n') && (c2 != -1)) {
                    if (!(in instanceof PushbackInputStream)) {
                        this.in = new PushbackInputStream(in);
                    }
                    ((PushbackInputStream)in).unread(c2);
                }
                break loop;
     
              default:
                if (--room < 0) {
                    buf = new char[offset + 128];
                    room = buf.length - offset - 1;
                    System.arraycopy(lineBuffer, 0, buf, 0, offset);
                    lineBuffer = buf;
                }
                buf[offset++] = (char) c;
                break;
            }
        }
        if ((c == -1) && (offset == 0)) {
            return null;
        }
        return String.copyValueOf(buf, 0, offset);
    }
     
    // 从“数据输入流”中读取“UTF范例”的值
    public final String readUTF() throws IOException {
        return readUTF(this);
    }
     
    public final static String readUTF(DataInput in) throws IOException {
        // 从“数据输入流”中读取“无标记的short范例”的值:
        // 留意:UTF-8输入流的前2个字节是数据的长度
        int utflen = in.readUnsignedShort();
        byte[] bytearr = null;
        char[] chararr = null;
     
        // 假如in自己是“数据输入流”,
        // 则,配置字节数组bytearr = "数据输入流"的成员bytearr
        //     配置字符数组chararr = "数据输入流"的成员chararr
        // 不然的话,新建数组bytearr和chararr
        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;
     
        // 从“数据输入流”中读取数据并存储到字节数组bytearr中;从bytearr的位置0开始存储,存储长度为utflen。
        // 留意,这里是存储到字节数组!并且读取的是全部的数据。
        in.readFully(bytearr, 0, utflen);
     
        // 将“字节数组bytearr”中的数据 拷贝到 “字符数组chararr”中
        // 留意:这里相当于“预处理惩罚的输入流中单字节的标记”,因为UTF-8是1-4个字节可变的。
        while (count < utflen) {
            // 将每个字节转换成int值
            c = (int) bytearr[count] & 0xff;
            // UTF-8的单字节数据的值都不会高出127;所以,高出127,则退出。
            if (c > 127) break;
            count++;
            // 将c生存到“字符数组chararr”中
            chararr[chararr_count++]=(char)c;
        }
     
        // 处理惩罚完输入流中单字节的标记之后,接下来我们继承处理惩罚。
        while (count < utflen) {
            // 下面语句执行了2步操纵。
            // (01) 将字节由 “byte范例” 转换成 “int范例”。
            //      譬喻, “11001010” 转换成int之后,是 “00000000 00000000 00000000 11001010”
            // (02) 将 “int范例” 的数据左移4位
            //      譬喻, “00000000 00000000 00000000 11001010” 左移4位之后,酿成 “00000000 00000000 00000000 00001100”
            c = (int) bytearr[count] & 0xff;
            switch (c >> 4) {
                // 若 UTF-8 是单字节,即 bytearr[count] 对应是 “0xxxxxxx” 形式;
                // 则 bytearr[count] 对应的int范例的c的取值范畴是 0-7。
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                    /* 0xxxxxxx*/
                    count++;
                    chararr[chararr_count++]=(char)c;
                    break;
     
                // 若 UTF-8 是双字节,即 bytearr[count] 对应是 “110xxxxx  10xxxxxx” 形式中的第一个,即“110xxxxx”
                // 则 bytearr[count] 对应的int范例的c的取值范畴是 12-13。
                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;
     
                // 若 UTF-8 是三字节,即 bytearr[count] 对应是 “1110xxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“1110xxxx”
                // 则 bytearr[count] 对应的int范例的c的取值是14 。
                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;
     
                // 若 UTF-8 是四字节,即 bytearr[count] 对应是 “11110xxx 10xxxxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“11110xxx”
                // 则 bytearr[count] 对应的int范例的c的取值是15 
                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);
    }
}


#p#副标题#e#

说明:

#p#分页标题#e#

DataInputStream 的浸染就是“答允应用措施以与呆板无关方法从底层输入流中读取根基 Java 数据范例。应用措施可以利用数据输出流写入稍后由数据输入流读取的数据。”

DataInputStream 中较量难以领略的函数就只有 readUTF(DataInput in);下面,对这个函数举办具体的先容,其它的函数请参考源码中的注释。

#p#分页标题#e#

readUTF(DataInput in)源码如下:

public final static String readUTF(DataInput in) throws IOException {
    // 从“数据输入流”中读取“无标记的short范例”的值:
    // 留意:UTF-8输入流的前2个字节是数据的长度
    int utflen = in.readUnsignedShort();
    byte[] bytearr = null;
    char[] chararr = null;
     
    // 假如in自己是“数据输入流”,
    // 则,配置字节数组bytearr = "数据输入流"的成员bytearr
    //     配置字符数组chararr = "数据输入流"的成员chararr
    // 不然的话,新建数组bytearr和chararr
    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;
     
    // 从“数据输入流”中读取数据并存储到字节数组bytearr中;从bytearr的位置0开始存储,存储长度为utflen。
    // 留意,这里是存储到字节数组!并且读取的是全部的数据。
    in.readFully(bytearr, 0, utflen);
     
    // 将“字节数组bytearr”中的数据 拷贝到 “字符数组chararr”中
    // 留意:这里相当于“预处理惩罚的输入流中单字节的标记”,因为UTF-8是1-4个字节可变的。
    while (count < utflen) {
        // 将每个字节转换成int值
        c = (int) bytearr[count] & 0xff;
        // UTF-8的每个字节的值都不会高出127;所以,高出127,则退出。
        if (c > 127) break;
        count++;
        // 将c生存到“字符数组chararr”中
        chararr[chararr_count++]=(char)c;
    }
     
    // 处理惩罚完输入流中单字节的标记之后,接下来我们继承处理惩罚。
    while (count < utflen) {
        // 下面语句执行了2步操纵。
        // (01) 将字节由 “byte范例” 转换成 “int范例”。
        //      譬喻, “11001010” 转换成int之后,是 “00000000 00000000 00000000 11001010”
        // (02) 将 “int范例” 的数据左移4位
        //      譬喻, “00000000 00000000 00000000 11001010” 左移4位之后,酿成 “00000000 00000000 00000000 00001100”
        c = (int) bytearr[count] & 0xff;
        switch (c >> 4) {
            // 若 UTF-8 是单字节,即 bytearr[count] 对应是 “0xxxxxxx” 形式;
            // 则 bytearr[count] 对应的int范例的c的取值范畴是 0-7。
            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                /* 0xxxxxxx*/
                count++;
                chararr[chararr_count++]=(char)c;
                break;
     
            // 若 UTF-8 是双字节,即 bytearr[count] 对应是 “110xxxxx  10xxxxxx” 形式中的第一个,即“110xxxxx”
            // 则 bytearr[count] 对应的int范例的c的取值范畴是 12-13。
            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;
     
            // 若 UTF-8 是三字节,即 bytearr[count] 对应是 “1110xxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“1110xxxx”
			// 查察本栏目

说明:

(01) readUTF()的浸染,是从输入流中读取UTF-8编码的数据,并以String字符串的形式返回。

(02) 知道了readUTF()的浸染之后,下面开始先容readUTF()的流程:

第1步,读取出输入流中的UTF-8数据的长度。代码如下:

int utflen = in.readUnsignedShort();

UTF-8数据的长度包括在它的前两个字节傍边;我们通过readUnsignedShort()读取出前两个字节对应的正整数就是UTF-8数据的长度。

#p#分页标题#e#

第2步,建设2个数组:字节数组bytearr 和 字符数组chararr。代码如下:

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

首先,判定该输入流自己是不是DataInputStream,即数据输入流;若是的话,

则,配置字节数组bytearr = "数据输入流"的成员bytearr

 配置字符数组chararr = "数据输入流"的成员chararr

不然的话,新建数组bytearr和chararr。

第3步,将UTF-8数据全部读取到“字节数组bytearr”中。代码如下:

in.readFully(bytearr, 0, utflen);

留意: 这里是存储到字节数组,而不是字符数组!并且读取的是全部的数据。

#p#分页标题#e#

第4步,对UTF-8中的单字节数据举办预处理惩罚。代码如下:

while (count < utflen) {
    // 将每个字节转换成int值
    c = (int) bytearr[count] & 0xff;
    // UTF-8的单字节数据的值都不会高出127;所以,高出127,则退出。
    if (c > 127) break;
    count++;
    // 将c生存到“字符数组chararr”中
    chararr[chararr_count++]=(char)c;
}

UTF-8的数据是变长的,可以是1-4个字节;在readUTF()中,我们最终是将全部的UTF-8数据生存到“字符数组(而不是字节数组)”中,再将其转换为String字符串。

由于UTF-8的单字节和ASCII沟通,所以这里就将它们举办预处理惩罚,直接生存到“字符数组chararr”中。对付其它的UTF-8数据,则在后头举办处理惩罚。

第5步,对“第4步 预处理惩罚”之后的数据,接着举办处理惩罚。代码如下:

// 处理惩罚完输入流中单字节的标记之后,接下来我们继承处理惩罚。
while (count < utflen) {
    // 下面语句执行了2步操纵。
    // (01) 将字节由 “byte范例” 转换成 “int范例”。
    //      譬喻, “11001010” 转换成int之后,是 “00000000 00000000 00000000 11001010”
    // (02) 将 “int范例” 的数据左移4位
    //      譬喻, “00000000 00000000 00000000 11001010” 左移4位之后,酿成 “00000000 00000000 00000000 00001100”
    c = (int) bytearr[count] & 0xff;
    switch (c >> 4) {
        // 若 UTF-8 是单字节,即 bytearr[count] 对应是 “0xxxxxxx” 形式;
        // 则 bytearr[count] 对应的int范例的c的取值范畴是 0-7。
        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
            /* 0xxxxxxx*/
            count++;
            chararr[chararr_count++]=(char)c;
            break;
     

        // 若 UTF-8 是双字节,即 bytearr[count] 对应是 “110xxxxx  10xxxxxx” 形式中的第一个,即“110xxxxx”
        // 则 bytearr[count] 对应的int范例的c的取值范畴是 12-13。
        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;
     
        // 若 UTF-8 是三字节,即 bytearr[count] 对应是 “1110xxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“1110xxxx”
        // 则 bytearr[count] 对应的int范例的c的取值是14 。
        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;
     
        // 若 UTF-8 是四字节,即 bytearr[count] 对应是 “11110xxx 10xxxxxx  10xxxxxx  10xxxxxx” 形式中的第一个,即“11110xxx”
        // 则 bytearr[count] 对应的int范例的c的取值是15 
        default:
            /* 10xx xxxx,  1111 xxxx */
            throw new UTFDataFormatException(
                "malformed input around byte " + count);
    }
}

#p#副标题#e#

(a) 我们将下面的两条语句一起举办说明

c = (int) bytearr[count] & 0xff;

switch (c >> 4) { ... }

首先,我们必需要领略 为什么要这么做(执行上面2条语句)呢?

原因很简朴,这么做的目标就是为了区分UTF-8数据是几位的;因为UTF-8的数据是1~4字节不等。

我们先看看UTF-8在1~4位环境下的名目。

--------------------+---------------------------------------------

1字节 UTF-8的通用名目  | 0xxxxxxx

2字节 UTF-8的通用名目  | 110xxxxx 10xxxxxx

3字节 UTF-8的通用名目  | 1110xxxx 10xxxxxx 10xxxxxx

4字节 UTF-8的通用名目  | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

执行 c = (int) bytearr[count] & 0xff; 和 c>>4 这2项操纵之后,上面的数据酿成

--------------------+---------------------------------------------

1字节 UTF-8的调动后对应的int范例值  | 00000000 00000000 00000000 00000xxx    (范畴是0~7)

2字节 UTF-8的调动后对应的int范例值  | 00000000 00000000 00000000 0000110x    (范畴是12~13)

3字节 UTF-8的调动后对应的int范例值  | 00000000 00000000 00000000 00001110    (范畴是14)

4字节 UTF-8的调动后对应的int范例值  | 00000000 00000000 00000000 00001111    (范畴是15)

为什么会是这样呢?

我们以“2字节 UTF-8的通用名目”来说明。

它的通用名目是 “110xxxxx 10xxxxxx”,我们在操纵时,只会操纵第1个字节,即只会操纵“110xxxxx”

(a.1) 在执行 c = (int) bytearr[count] & 0xff; 时,首先将 bytearr[count] 转换成int。

“110xxxxx”

转成int范例之后,酿成

“11111111 11111111 11111111 110xxxxx”

因为“110xxxxx”是负数(第1为是1),所以转换成int范例时多出来的位补1。

(a.2) 接着 c = (int) bytearr[count] & 0xff; 中,会将 “转换成int范例后的bytearr[count]” 与 “0xff”举办 逻辑与(即&) 操纵。功效如下:

“00000000 00000000 00000000 110xxxxx”

(a.3) 执行 c>>4 时,会将上面的功效左移4位。获得的功效如下:

“00000000 00000000 00000000 0000110x”

(b) 上面的领略之后,swicth (c>>4) { ... } 个中的省略号部门就相当容易领略了。

我们照旧以“2字节 UTF-8的通用名目”来说明。

#p#分页标题#e#

它会执行 case 12 和 case 13;源码如下:

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

(b.1) 由于这种环境对应的UTF-8数据是“2字节”的,因此,执行count+2;直接跳过2个字节。

(b.2) 由于chararr的元素是字符范例,而一个字符正好占2个字节;因为正好将(((c & 0x1F) << 6) | (char2 & 0x3F)); 的功效转换成char,然后生存在chararr数组中。

第6步,将字符数组转换成String字符串,并返回。代码如下:

return new String(chararr, 0, chararr_count);

#p#副标题#e#

示例代码

关于DataInputStream中API的具体用法,参考示例代码(DataInputStreamTest.java):

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.lang.SecurityException;
     
/**
 * DataInputStream 和 DataOutputStream测试措施
 *
 * @author skywang
 */
public class DataInputStreamTest {
     
    private static final int LEN = 5;
     
    public static void main(String[] args) {
        // 测试DataOutputStream,将数据写入到输出流中。
        testDataOutputStream() ;
        // 测试DataInputStream,从上面的输出流功效中读取数据。
        testDataInputStream() ;
    }
     
    /**
     * DataOutputStream的API测试函数
     */
    private static void testDataOutputStream() {
     
        try {
            File file = new File("file.txt");
            DataOutputStream out =
                  new DataOutputStream(
                      new FileOutputStream(file));
     
            out.writeBoolean(true);
            out.writeByte((byte)0x41);
            out.writeChar((char)0x4243);
            out.writeShort((short)0x4445);
            out.writeInt(0x12345678);
            out.writeLong(0x0FEDCBA987654321L);
     
            out.writeUTF("abcdefghijklmnopqrstuvwxyz严12");
     
            out.close();
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }
    /**
     * DataInputStream的API测试函数
     */
    private static void testDataInputStream() {
     
        try {
            File file = new File("file.txt");
            DataInputStream in =
                  new DataInputStream(
                      new FileInputStream(file));
     
            System.out.printf("byteToHexString(0x8F):0x%s\n", byteToHexString((byte)0x8F));
            System.out.printf("charToHexString(0x8FCF):0x%s\n", charToHexString((char)0x8FCF));
     
            System.out.printf("readBoolean():%s\n", in.readBoolean());
            System.out.printf("readByte():0x%s\n", byteToHexString(in.readByte()));
            System.out.printf("readChar():0x%s\n", charToHexString(in.readChar()));
            System.out.printf("readShort():0x%s\n", shortToHexString(in.readShort()));
            System.out.printf("readInt():0x%s\n", Integer.toHexString(in.readInt()));
            System.out.printf("readLong():0x%s\n", Long.toHexString(in.readLong()));
            System.out.printf("readUTF():%s\n", in.readUTF());
     
            in.close();
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }
     
    // 打印byte对应的16进制的字符串
    private static String byteToHexString(byte val) {
        return Integer.toHexString(val & 0xff);
    }
     
    // 打印char对应的16进制的字符串
    private static String charToHexString(char val) {
        return Integer.toHexString(val);
    }
     
    // 打印short对应的16进制的字符串
    private static String shortToHexString(short val) {
        return Integer.toHexString(val & 0xffff);
    }
}

#p#副标题#e#

运行功效:

byteToHexString(0x8F):0x8f

charToHexString(0x8FCF):0x8fcf

readBoolean():true

readByte():0x41

readChar():0x4243

readShort():0x4445

readInt():0x12345678

readLong():0xfedcba987654321

readUTF():abcdefghijklmnopqrstuvwxyz严12

功效说明:

(01) 查察file.txt文本。16进制的数据显示如下:

java io学习(十三) 数据输入流的认知、源码和示例

#p#分页标题#e#

001f 对应的int值是31。它暗示的寄义是后头的UTF-8数据的长度。字符串“abcdefghijklmnopqrstuvwxyz严12”中字母“ab...xyz”的长度是26,“严”对应的UTF-8数据长度是3;“12”长度是2。总的长度=26+3+2=31。

(02) 返回byte对应的16进制的字符串

源码如下:

private static String byteToHexString(byte val) {

return Integer.toHexString(val & 0xff);

}

想想为什么代码是:

return Integer.toHexString(val & 0xff);

而不是

return Integer.toHexString(val);

我们先看看 byteToHexString((byte)0x8F); 在上面两种环境下的输出功效。

return Integer.toHexString(val & 0xff); 对应的输出是“0xffffff8f”

return Integer.toHexString(val); 对应的输出是“0x8f”

为什么会这样呢?

原因其实很简朴,就是“byte范例转换成int范例”导致的问题。

byte范例的0x8F是一个负数,它对应的2进制是10001111;将一个负数的byte转换成int范例时,执行的是有标记转型(新增位都填充标记位的数字)。0x8F的标记位是1,因为将它转换成int时,填充“1”;转型后的功效(2进制)是11111111 11111111 11111111 10001111,对应的16进制为0xffffff8f。

因为当我们执行Integer.toHexString(val);时,返回的就是0xffffff8f。

在Integer.toHexString(val & 0xff)中,相当于0xffffff8f & 0xff,获得的功效是0x8f。

(03) 返回char和short对应的16进制的字符串

“返回char对应的16进制的字符串”对应的源码如下:

private static String charToHexString(char val) {

return Integer.toHexString(val);

}

“返回short对应的16进制的字符串”对应源码如下:

private static String shortToHexString(short val) {

return Integer.toHexString(val & 0xffff);

}

较量上面的两个函数,为什么一个是 “val” ,而另一个是 “val & 0xffff”?

通过(02)的阐明,我们雷同的推出为什么 “返回short对应的16进制的字符串” 要执行“val & 0xffff”。

可是,为什么 “返回char对应的16进制的字符串” 要执行 “val” 即可。原因也很简朴,java中char是无标记范例,占两个字节。将char转换为int范例,执行的是无标记转型,新增为都填充0。

来历:http://www.cnblogs.com/skywang12345/p/io_14.html

 

    关键字:


天才代写-代写联系方式