暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java IO流

洋洋洒洒 2025-08-08
18

Java IO流采用装饰器模式,允许通过组合不同流来逐层添加功能。以FileInputStreamBufferedInputStreamDataInputStream装饰为例,其层次结构和功能如下:


1. 基础流:FileInputStream

  • 功能:直接从文件读取原始字节数据。

  • 特点:无缓冲,每次读取需系统调用,效率较低。


2. 第一层装饰:BufferedInputStream

  • 作用:为底层流(如FileInputStream)添加缓冲功能。

  • 原理:

    • 维护一个内存缓冲区,批量读取数据块(默认8192字节)。

    • 读取时优先从缓冲区取数据,减少磁盘访问次数。

  • 优势:显著提升读取效率,尤其适用于频繁小数据读取的场景。


3. 第二层装饰:DataInputStream

  • 作用:将字节流转换为高级数据类型(如intdouble)。

  • 原理:

    • 基于底层流(如BufferedInputStream)读取字节,并按大端序解析为数据类型。

    • 提供便捷方法(如readInt()readDouble()),避免手动拼接字节。

  • 依赖:需依赖底层流的缓冲功能以保证高效读取。


组合顺序与性能优化

  • 推荐顺序:

    FileInputStream → BufferedInputStream→DataInputStream

    原因:

    1. 缓冲优先:先通过BufferedInputStream减少磁盘I/O次数。

    2. 解析后置DataInputStream在缓冲基础上解析数据,避免频繁读取。

    • 反例:若先DataInputStreamBufferedInputStream,解析时仍需多次读取底层流,效率较低。

代码示例

import java.io.*;

public class IODecoratorExample {
   public static void main(String[] args) throws IOException {
       // 创建基础流
       try (FileInputStream fis = new FileInputStream("data.bin");
            // 添加缓冲功能
            BufferedInputStream bis = new BufferedInputStream(fis);
            // 添加数据解析功能
            DataInputStream dis = new DataInputStream(bis)) {
           
           // 读取整数(利用缓冲和解析)
           int value = dis.readInt();
           System.out.println("Read int: " + value);
      } // 自动关闭所有流
  }
}

关键特性总结

装饰器功能核心方法示例
BufferedInputStream缓冲读写,减少I/O次数read()(从缓冲区取数据)
DataInputStream字节到数据类型的解析readInt(), readDouble()

注意事项

  1. 关闭流:只需关闭最外层流(如DataInputStream),底层流会自动关闭。

  2. 性能考量:

    • 缓冲区大小可通过构造函数调整(如new BufferedInputStream(fis, 1024))。

    • 过度装饰可能增加内存开销,需按需组合。

  3. 异常处理:确保在try-with-resources中使用流,避免资源泄漏。

应用场景

  • 文件读取:高效读取结构化二进制文件(如音频头、图像元数据)。

  • 网络传输:在Socket流上添加缓冲和解析功能,提升数据传输效率。

通过合理组合装饰器,可以在不修改原有代码的情况下,灵活扩展IO流的功能,同时保持高性能和高可维护性。



DataInputStream 是 Java 中用于从二进制流中读取基本数据类型和字符串的核心类,常用于解析由 DataOutputStream 写入的二进制文件或网络传输的数据。以下是使用方法及注意事项的总结:

一、核心使用步骤

  1. 创建基础输入流 通常以 FileInputStream 为基础,指向目标文件或数据源。

    FileInputStream fis = new FileInputStream("data.bin");
  2. 包装为 DataInputStream 直接通过构造函数将基础流传入,或结合 BufferedInputStream 提升效率。

    // 推荐搭配缓冲流,减少磁盘IO次数
    try (DataInputStream dis = new DataInputStream(
    new BufferedInputStream(fis))) {
    // 读取数据
    }
  3. 按顺序读取数据 根据数据写入顺序,调用对应的 read 方法(如 readInt()readDouble() 等)。


二、常用读取方法

方法返回类型作用
readInt()int读取4字节整数(大端序)
readLong()long读取8字节长整数
readFloat()float读取4字节单精度浮点数
readDouble()double读取8字节双精度浮点数
readBoolean()boolean读取1字节布尔值
readUTF()String读取带长度前缀的字符串
readFully(byte[] b)-填充字节数组(需完全读取)

示例:读取包含 int 和 double 的文件

try (DataInputStream dis = new DataInputStream(
  new BufferedInputStream(new FileInputStream("data.bin")))) {
  int intValue = dis.readInt();     // 读取整数
  double doubleValue = dis.readDouble(); // 读取双精度浮点数
  System.out.println("Int: " + intValue + ", Double: " + doubleValue);
}

三、关键注意事项

  1. 字节序(Endian) DataInputStream 默认使用大端序(Big-endian),若数据为小端序需手动转换或使用 ByteBuffer

  2. 异常处理

    • 读取过程中可能抛出 EOFException(文件末尾未读完)或 IOException,需捕获或抛出。

    • 使用 try-with-resources 自动关闭流,避免资源泄漏。

  3. 数据对齐 读取顺序必须与数据写入顺序严格一致,否则会导致解析错误。

  4. 性能优化

    • 通过 BufferedInputStream 包装基础流,减少磁盘/网络IO次数。

    • 避免频繁调用单字节读取方法(如 readByte()),优先使用批量读取(如 readFully())。


四、典型应用场景

  1. 解析二进制文件 读取自定义格式的二进制文件(如配置文件、数据存储文件)。

    // 示例:读取含布尔值和字符串的文件
    boolean flag = dis.readBoolean();
    String json = dis.readUTF();
  2. 网络数据传输 Socket 输入流中读取二进制协议数据。

    DataInputStream dis = new DataInputStream(socket.getInputStream());
    int messageType = dis.readInt();
    byte[] data = new byte[dis.readInt()];
    dis.readFully(data);
  3. 替代手工字节解析 相比手动拼接字节(如 ByteBuffer),DataInputStream 更直观且代码量更少。


五、扩展技巧

  1. 读取字节数组 若需解析原始字节,可先用 read(byte[]) 读取到数组,再进一步处理。

    byte[] buffer = new byte[1024];
    int bytesRead = dis.read(buffer); // 返回实际读取的字节数
  2. 处理混合数据类型 结合 readFully() 和偏移量读取复杂结构(如嵌套对象)。


总结

DataInputStream 通过简单的方法封装了二进制数据的解析逻辑,适用于大多数基本数据类型的读取场景。使用时需注意字节序、异常处理和资源管理,并通过 BufferedInputStream 提升性能。对于复杂二进制协议或高性能需求,可结合 ByteBuffer 或第三方库(如 Protobuf)。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论