DataInput的架构

image.png

DataInput的基类

DataOutput概述

DataInput 接口提供从二进制流中读取字节并从它们重构任何 Java 基本类型的数据。 还有一种工具可以从修改后的 UTF-8 格式的数据中重建字符串。 对于此接口中的所有读取例程,如果在读取所需字节数之前到达文件末尾,则通常会抛出 EOFException(这是一种 IOException)。 如果由于文件结尾以外的任何原因无法读取任何字节,则抛出 EOFException 以外的 IOException。 特别是,如果输入流已关闭,则可能会抛出 IOException。

DataInput 和 DataOutput 接口的经过修改的 UTF-8 实现表示 Unicode 字符串,其格式是对 UTF-8 稍作修改的格式。 (有关标准 UTF-8 格式的信息,请参阅 The Unicode Standard, Version 4.0 的 3.9 Unicode Encoding Forms 部分)。 请注意,在下表中,最高有效位出现在最左侧的列中。

image.png

此格式与标准 UTF-8 格式的区别如下:空字节 ‘\u0000’ 以 2 字节格式而不是 1 字节格式编码,因此编码的字符串永远不会嵌入空值。仅使用 1 字节、2 字节和 3 字节格式。补充字符以代理对的形式表示。

UML概述

image.png

重要方法

readFully

从输入流中读取一些字节并将它们存储到缓冲区数组 b 中。 读取的字节数等于 b 的长度。此方法会阻塞,直到出现以下情况之一:

  • b.length 字节的输入数据可用,在这种情况下会正常返回。
  • 检测到文件结尾,在这种情况下会抛出 EOFException。
  • 发生 I/O 错误,在这种情况下会抛出 EOFException 以外的 IOException。

如果 b 为 null,则抛出 NullPointerException。 如果 b.length 为零,则不读取任何字节。 否则,读取的第一个字节存储到元素 b[0] 中,下一个存储到 b[1] 中,依此类推。 如果此方法抛出异常,则可能是 b 的部分而非全部字节已使用输入流中的数据进行了更新。

  1. void readFully(byte b[]) throws IOException;

skipBytes

尝试从输入流中跳过 n 个字节的数据,丢弃跳过的字节。 但是,它可能会跳过一些较小的字节数,可能为零。 这可能由多种情况中的任何一种引起; 在跳过 n 个字节之前到达文件末尾只是一种可能性。 此方法从不抛出 EOFException。 返回实际跳过的字节数。

  1. int skipBytes(int n) throws IOException;

readBoolean

读取一个输入字节,如果该字节非零则返回true,如果该字节为零则返回false。该方法适用于读取接口DataOutput的writeBoolean方法所写的字节。返回:布尔值读取。

  1. boolean readBoolean() throws IOException;

readByte

读取并返回一个输入字节。字节被视为-128到127(包括在内)范围内的带符号值。该方法适用于读取接口DataOutput的writeByte方法所写的字节。返回: 读取8位的值。

  1. byte readByte() throws IOException;

readUnsignedByte

读取一个输入字节,将其零扩展为 int 类型,并返回结果,因此范围在 0 到 255 之间。如果 writeByte 的参数是 应为 0 到 255 范围内的值。

  1. int readUnsignedByte() throws IOException;

readShort

读取两个输入字节并返回一个短值。 设 a 为读取的第一个字节,b 为第二个字节。 该方法适用于读取接口DataOutput的writeShort方法写入的字节。
返回的值为: (short)((a << 8) | (b & 0xff))
short占两个字节,第一个字节向左边偏移8位,再接上第二个字节,就变成一个short了

  1. short readShort() throws IOException;

int readUnsignedShort() throws IOException;

读取两个输入字节并返回0到65535范围内的int值。设a是读取的第一个字节,b是读取的第二个字节。返回值为:
((a & 0xff) << 8) | (b & 0xff))
如果writeShort的参数打算为0到65535范围内的值,则此方法适合读取接口DataOutput的writeShort方法写入的字节。返回:读的16位无符号值。

((a & 0xff) << 8) | (b & 0xff))意味着什么
short是一个由两个字节构成的数值

0xff意味着什么
0ff是一个32位的int,即 00000000 00000000 00000000 11111111

(a & 0xff)意味着什么
a 是一个八位的字节,如果最高位为1则是一个负数,我们希望忽略这个符号位,把这个符号位也作为数据位,那么short的取值范围就不够了,因此short要提升为int来存储

例如:字节a = 10000000 = -128的十进制,如果要变成无符号的类型,则数据类型要提升一级,并保持原字节的位不变,高位补0

字节a = 10000000 提升为 int的二进制为: 00000000 00000000 00000000 10000000
0xff隐式是一个int类型,即它的二进制为: 00000000 00000000 00000000 11111111

  1. (a & 0xff) = **00000000 00000000 00000000** **10000000**<br /> & **00000000 00000000 00000000** 11111111<br /> -----------------------------------------------------------<br /> **00000000 00000000 00000000** **10000000**

(a & 0xff) << 8意味着什么
第一个字节往左边错开8位
00000000 00000000 00000000 10000000
~~00000000 ~~00000000 10000000 00000000 00000000

((a & 0xff) << 8) | (b & 0xff))意味着什么

第一个字节和第二个字节的 | 运算

  1. int readUnsignedShort() throws IOException;

readChar

读取两个输入字节并返回一个char值。设a是读取的第一个字节,b是读取的第二个字节。返回值为:

(a << 8) | (b & 0xff))

该方法适用于读取接口DataOutput的writeChar方法写入的字节。

  1. char readChar() throws IOException

readInt

读取四个输入字节并返回一个int值。让a-d成为第一个到第四个字节。返回值为:

意味着低位不变,高位补0,再向左错开24个位置,再低位补0
((a & 0xff) << 24) |
意味着低位不变,高位补0,再向左错开16个位置,再低位补0
((b & 0xff) << 16) |
意味着低位不变,高位补0,再向左错开8个位置,再低位补0
(c & 0xff) << 8) |
意味着低位不变,高位补0,再向左错开0个位置,再低位补0
(d & 0xff))

最后 | 4个int中的每个位

该方法适用于读取接口DataOutput的writeInt方法写入的字节。

原理同上

  1. int readInt() throws IOException;

readLong

读取8个输入字节并返回一个长值。让a-h成为第一个到第8个字节。返回值为:

((long)(a & 0xff) << 56) |
(long)(b & 0xff) << 48) |
(long)(c & 0xff) << 40) |
(long)(d & 0xff) << 32) |
((long)(e & 0xff) << 24) |
(long)(f & 0xff) << 16) |
(long)(g & 0xff) << 8) |
(long)(h & 0 xff)))

该方法适用于读取接口DataOutput的writeLong方法写入的字节。

  1. long readLong() throws IOException;

readFloat

读取四个输入字节并返回一个浮点值。它首先按照readInt方法的方式构造一个int值,然后按照float . intbitstfloat方法的方式将这个int值转换为一个浮点数。该方法适用于读取接口DataOutput的writeFloat方法写入的字节。

  1. float readFloat() throws IOException;

readDouble

读取8个输入字节并返回一个双精度值。它首先按照readLong方法的方式构造一个长值,然后按照方法double . longbitstodouble的方式将这个长值转换为一个double值。该方法适用于读取接口DataOutput的writdouble方法写入的字节。

  1. double readDouble() throws IOException;

readLine

从输入流中读取下一行文本。它读取连续的字节,将每个字节分别转换为一个字符,直到遇到行结束符或文件结束符;读取的字符然后作为字符串返回。注意,因为这个方法处理字节,所以它不支持完整的Unicode字符集的输入。
如果在读取一个字节之前遇到文件结束,则返回null。否则,读取的每个字节将通过零扩展名转换为char类型。如果遇到字符’\n’,它将被丢弃并停止读取。如果遇到字符’\r’,它将被丢弃,如果下面的字节转换为字符’\n’,它也将被丢弃;然后停止阅读。如果在’\n’和’\r’之前遇到文件结束符,则停止读取。一旦停止读取,返回一个String,它包含所有已读且未丢弃的字符,并按顺序获取。注意,这个字符串中的每个字符的值都小于\u0100,即(char)256。

返回:输入流中的下一行文本,如果在读取字节之前遇到文件的末尾,则为空。

  1. double readLine() throws IOException;

readUTF

读取使用修改后的UTF-8格式编码的字符串。readUTF的通用约定是,它读取以修改后的UTF-8格式编码的Unicode字符串的表示;然后这个字符串作为string返回。
首先,读取两个字节,并按照readUnsignedShort方法的方式构造一个无符号16位整数。这个整数值称为UTF长度,指定要读取的额外字节数。然后,通过将这些字节分组,将它们转换为字符。每个组的长度从组的第一个字节的值计算。组后面的字节(如果有的话)是下一组的第一个字节。

如果组的第一个字节匹配位模式0xxxxxxx (x表示“可能是0或1”),则组仅由该字节组成。字节被零扩展成一个字符。

如果一组匹配的第一个字节位模式110 xxxxx,然后组由一个和第二个字节的字节b。如果没有字节b(因为是最后一个字节的字节读),或者如果字节b位模式10 xxxxxx不匹配,则会抛出UTFDataFormatException。否则,将组转换为字符:

(char)((a & 0x1F) << 6) | (b & 0x3F)

如果一组匹配的第一个字节位模式1110 xxxx,然后组由一个和两个字节的字节b和c。如果没有字节c(因为字节的最后两个字节的读),或字节或字节b c位模式10 xxxxxx不匹配,则会抛出UTFDataFormatException。否则,将组转换为字符:

(char) (((& 0 x0f) < < 12) | ((b & 0 x3f) < < 6) | (c & 0 x3f))

  1. double readUTF() throws IOException;