Java IO:DataInputStream 类

Java 中的 DataInputStream 类(位于java.io包下),能够让开发者从 InputStream 中读取 Java 基本数据类型(如int、float、long等),而不只是读取原始字节。具体操作时,将 InputStream 封装在 DataInputStream 内,之后便可借助 DataInputStream 来读取 Java 基本数据类型。它之所以被称作DataInputStream,正是因为其读取的是数据(数值),而非单纯的字节 。

image.png

当你需要读取的数据包含大于单字节的 Java 基本数据类型(像 int、long、float、double 等)时,DataInputStream 会是个极为实用的工具。DataInputStream 要求多字节的基本数据类型按照网络字节顺序(大端字节序,即最重要的字节排在最前面)进行写入。注意:

(1)通常你会使用 DataInputStream 来读取 DataOutputStream 写入的数据。

(2)DataInputStream 类是 InputStream 的子类。这意味着 DataInputStream 同样具备基础的读取功能,它能够从底层的 InputStream 中读取单个字节,或者将数据读取到字节数组里,以满足一些特定场景的需求。

(3)在读取原始数据类型时,我们无法区分有效的 int 值 -1 和正常的流结束标记。这实际上表明,从返回的原始数据值里,我们无法判断是否已经抵达流的末尾。所以,你必须预先知晓要读取的数据类型及其顺序。简单来说,你得提前清楚能从 DataInputStream 中读取哪些数据。

DataInputStream 示例

下面是一个 DataInputStream 示例:

package com.hxstrive.java_io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.nio.ByteBuffer;

public class DataInputStreamExample {

    public static void main(String[] args) throws Exception {
        // 准备数据,一个字节数组
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        // 写入一个字节
        output.write(10);
        // 一个 int
        output.write(ByteBuffer.allocate(4).putInt(128).array());
        // 一个 float
        output.write(ByteBuffer.allocate(4).putFloat(58.34f).array());
        // 一个 double
        output.write(ByteBuffer.allocate(8).putDouble(5089.04f).array());

        // 尝试从 DataInputStream 读取数据
        try (DataInputStream input = new DataInputStream(new ByteArrayInputStream(output.toByteArray()))) {
            int aByte = input.read();
            System.out.println("aByte=" + aByte);

            int anInt = input.readInt();
            System.out.println("anInt=" + anInt);

            float aFloat = input.readFloat();
            System.out.println("aFloat=" + aFloat);

            double aDouble = input.readDouble();
            System.out.println("aDouble=" + aDouble);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

运行输出:

aByte=10
anInt=128
aFloat=58.34
aDouble=5089.0400390625

上面示例,创建了一个 ByteArrayOutputStream 类,利用 ByteBuffer 类向 OutputStream 中分别写入 byte、int、float 和 double 类型的样例数据,使用 output.toByteArray() 方法获取样例数据的字节数组去创建 DataInputStream。最后,从 DataInputStream 中读取刚刚写入的 byte、int、float 和 double 样例数据。

创建 DataInputStream

你可以利用构造函数来创建 Java 的 DataInputStream 对象。在创建过程中,你需要传入一个 InputStream 作为参数,DataInputStream 会从这个 InputStream 里读取原始数据类型的数据。

示例:

DataInputStream dataInputStream = new DataInputStream(new FileInputStream("data.bin"));

使用 DataInputStream 和 DataOutputStreamm

如前所述,DataInputStream 类经常与 DataOutputStream 类一起使用。下面举例说明先用 DataOutputStream 写入数据,然后再用 DataInputStream 读取数据。示例:

package com.hxstrive.java_io;

import java.io.*;

public class DataInputStreamExample2 {

    public static void main(String[] args) throws IOException {
        // 临时存放数据
        ByteArrayOutputStream output = new ByteArrayOutputStream();

        // 写入数据到 DataOutputStream
        try (DataOutputStream dataOutputStream = new DataOutputStream(output)) {
            dataOutputStream.writeInt(123);
            dataOutputStream.writeFloat(123.45F);
            dataOutputStream.writeLong(789);
        }

        // 使用 DataInputStream 读取 DataOutputStream 写出的数据
        try(DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(output.toByteArray()))) {
            int int123 = dataInputStream.readInt();
            float float12345 = dataInputStream.readFloat();
            long long789 = dataInputStream.readLong();
            System.out.println("int123 = " + int123);
            System.out.println("float12345 = " + float12345);
            System.out.println("long789 = " + long789);
        }
    }
}

运行输出:

int123 = 123
float12345 = 123.45
long789 = 789

上述示例,首先创建 DataOutputStream 类,然后将 int、float 和 long 值写入 ByteArrayOutputStream,临时存放(当然,你也可以直接写入到某个文件)。其次,示例创建了一个 DataInputStream,从 ByteArrayOutputStream 返回的字节数组中读入 int、float 和 long 值。

常用方法

  • readBoolean() 方法从 DataInputStream 中读取布尔值。

  • readByte() 方法从 DataInputStream 中读取字节。

  • readUnsignedByte() 方法从 DataInputStream 读取 Java 无符号字节(只有正值)。无符号字节会以 int 的形式返回,因为超过 127 的字节值无法放入有符号字节数据类型中。

  • readChar() 方法从 DataInputStream 中读取字符。

  • readDouble() 方法从 DataInputStream 中读取double。

  • readFloat() 方法从 DataInputStream 中读取 float。

  • readShort() 方法从 DataInputStream 中读取 short。

  • readUnsignedShort() 方法从 DataInputStream 读取 Java 无符号 short(只有正值)。无符号短字符将作为 int 返回,因为超过 32767 的短字符值无法放入有符号短字符数据类型中。

  • readInt() 方法从 DataInputStream 中读取一个 int。

  • readLong() 方法从 DataInputStream 中读取 long。

  • readUTF() 方法从 DataInputStream 中读取字符串。注意,要使用该方法读取数据,数据必须以 UTF-8 编码。

关闭 DataInputStream

当你完成从 DataInputStream 中读取数据的操作后,务必记得将其关闭。需要注意的是,关闭 DataInputStream 时,与之关联的用于读取数据的 InputStream 实例也会随之关闭。

若要关闭 DataInputStream,只需调用其 close() 方法即可。下面为你展示关闭 DataInputStream 的具体操作流程:

dataInputStream.close();

你还可以使用 Java 7 中引入的 try-with-resources 结构。例如:

InputStream input = new FileInputStream("data.bin");
try(DataInputStream dataInputStream = new DataInputStream(input)){
    int data = dataInputStream.readInt();
    //....
}

需留意的是,此处已不存在任何显式的 close() 方法调用。这是因为 try-with-resources 结构已自动处理了资源关闭的问题。

同时还要注意,第一个 FileInputStream 实例并非在 try-with-resources 代码块中创建。这表明 try-with-resources 块不会自动关闭该 FileInputStream 实例。然而,由于关闭 DataInputStream 时,它会同时关闭其用于读取数据的 InputStream 实例,所以 FileInputStream 实例会在 DataInputStream 关闭时一同被关闭 。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号