Skip to content

DataInputStream 读取基本类型

你有没有想过:为什么 Java 的基本类型(int、long、double)可以方便地写入文件和从文件读取?

答案是 DataInputStream

DataInputStreamDataOutputStream 是一对,它们以二进制格式读写 Java 基本类型,比文本格式更紧凑、更精确(不会有精度损失)。

基本用法

java
try (DataInputStream dis = new DataInputStream(
        new BufferedInputStream(
            new FileInputStream("data.bin")))) {
    int i = dis.readInt();           // 4 字节
    long l = dis.readLong();         // 8 字节
    double d = dis.readDouble();     // 8 字节
    boolean b = dis.readBoolean();   // 1 字节
    String s = dis.readUTF();        // 变长:2 字节长度 + N 字节内容
}

读取方法一览

方法返回类型字节数
readBoolean()boolean1
readByte()byte1
readUnsignedByte()int1
readChar()char2
readShort()short2
readUnsignedShort()int2
readInt()int4
readLong()long8
readFloat()float4
readDouble()double8
readUTF()String变长

readUTF() 的格式

readUTF() 读取的是 writeUTF() 写入的格式:

[2 字节长度][N 字节 UTF-8 内容]
java
// 写入 "Hello"
dos.writeUTF("Hello");
// 实际写入:[00, 05, 48, 65, 6c, 6c, 6f]
//           长度 5,H  e  l  l  o

// 读取
String s = dis.readUTF();
// 读取前 2 字节得到长度 5,再读 5 字节得到内容

注意readUTF() / writeUTF() 是配套的,不能和 readChars() / writeChars() 混用。

处理文件结束

java
try (DataInputStream dis = new DataInputStream(
        new BufferedInputStream(
            new FileInputStream("data.bin")))) {
    try {
        while (true) {
            int id = dis.readInt();
            String name = dis.readUTF();
            System.out.println(id + ": " + name);
        }
    } catch (EOFException e) {
        // 文件结束,正常退出
    }
}

读取字节数组

DataInputStream 没有直接的 read(byte[]) 方法,需要用 readFully()

java
try (DataInputStream dis = new DataInputStream(
        new BufferedInputStream(
            new FileInputStream("data.bin")))) {
    byte[] buf = new byte[1024];
    dis.readFully(buf); // 读取恰好 1024 字节,不够就抛异常

    // 读取指定字节数
    dis.readFully(buf, 0, 100); // 读取前 100 字节
}

读取大端序 / 小端序

DataInputStream 只支持大端序(高位字节在前)。小端序需要自己处理:

java
public static int readIntLittleEndian(DataInputStream dis)
        throws IOException {
    int ch1 = dis.read();
    int ch2 = dis.read();
    int ch3 = dis.read();
    int ch4 = dis.read();
    return (ch4 << 24) | (ch3 << 16) | (ch2 << 8) | (ch1);
}

配合 Buffered 使用

永远配合 BufferedInputStream 使用

java
// ❌ 差:没有缓冲
DataInputStream dis = new DataInputStream(
    new FileInputStream("data.bin"));

// ✅ 好:有缓冲
DataInputStream dis = new DataInputStream(
    new BufferedInputStream(
        new FileInputStream("data.bin")));

常见错误

类型不匹配

java
// ❌ 写入 int,读取 long
dos.writeInt(42);
long value = dis.readLong(); // 读错了 8 字节而不是 4 字节

// ❌ writeUTF 和 readLine 混用
dos.writeUTF("Hello");
String s = dis.readLine(); // readLine 不适合读 writeUTF 的格式!

不处理 EOF

java
// ❌ 没有处理 EOF
int value = dis.readInt(); // 读到文件末尾会抛 EOFException

// ✅ 正确处理
try {
    while (true) {
        int value = dis.readInt();
        process(value);
    }
} catch (EOFException e) {
    // 文件结束
}

记住这个约束

读写顺序必须一致,写了什么类型就读什么类型。 DataInputStream 和 DataOutputStream 是一对,不能混用其他格式。

基于 VitePress 构建