FileInputStream 只能按字节读取原始二进制数据,无法直接读取 int、double 等基本类型;DataInputStream 是其装饰器,提供 readInt()、readDouble() 等方法,按 Java 标准格式解析多字节数据。

FileInputStream 本身不能直接读取 Java 基本数据类型(如 int、double、boolean),它只按字节(byte)读取原始二进制数据;DataInputStream 则是在 FileInputStream 等节点流之上封装的处理流,专门提供读取基本类型变量的方法,比如 readInt()、readDouble()、readUTF() 等。
功能定位不同:一个负责“连文件”,一个负责“解数据”
FileInputStream 是节点流,直接与磁盘文件建立连接,只做最底层的字节搬运——每次调用 read() 得到一个 int(实际是低 8 位有效),无法自动识别多字节整数或字符串结构。DataInputStream 不具备独立访问文件的能力,必须包装一个已存在的输入流(如 FileInputStream),它的作用是按 Java 的标准二进制格式(如 big-endian)把连续字节重新解释为有意义的基本类型值。
使用方式不同:不能单独创建,必须组合使用
DataInputStream 没有直接关联文件的构造方法,必须传入一个 InputStream 实例:
- ✅ 正确写法:
new DataInputStream(new FileInputStream("data.bin")) - ❌ 错误写法:
new DataInputStream("data.bin")(编译不通过)
这种组合体现了装饰器模式:FileInputStream 提供“从哪读”,DataInputStream 提供“怎么读”。关闭时只需关闭外层的 DataInputStream,它会自动委托关闭底层 FileInputStream。
读取行为差异:字节 vs 类型语义
假设文件中按顺序存了 4 字节的 int(0x0000000A)、2 字节的 short(0x0014)、1 字节的 boolean(0x01):
- 用
FileInputStream.read()连续调用 7 次,得到的是 7 个独立的int值:0, 0, 0, 10, 0, 20, 1 - 用
DataInputStream.readInt()→ 返回10(自动合并 4 字节)
接着readShort()→ 返回20
接着readBoolean()→ 返回true
也就是说,FileInputStream 只管“字节流长度”,DataInputStream 还管“字节如何分组并映射为 Java 类型”。
适用场景明确:二进制协议文件离不开 DataInputStream
当文件是 Java 程序用 DataOutputStream 写出的(例如保存配置、序列化简单结构体、网络协议包),就必须用 DataInputStream 配套读取,否则手动拼接字节极易出错。而纯文本或不确定格式的文件,一般用 FileReader 或 BufferedReader 更合适。


















