DataOutputStream 终极解析与记忆指南
一、核心本质
DataOutputStream
是 Java 提供的数据字节输出流,继承自 FilterOutputStream
,用于写入基本数据类型和字符串的二进制数据。
作用:1.将java程序中的数据直接写入到文件,写到文件中就是二进制。
2.DataOutputStream写的效率很高,原因:写的过程不需要转码。
3.DataOutputStream写到文件中的数据,只能由DataInputStream来读取。
核心特性速查表
特性 | 说明 |
---|---|
继承链 | OutputStream → FilterOutputStream → DataOutputStream |
数据写入 | 提供多种写入基本数据类型的方法 |
字节顺序 | 使用大端序(Big-endian) |
典型用途 | 生成由 DataInputStream 读取的二进制文件 |
线程安全 | 否 |
二、构造方法
java
// 唯一构造方法(需包装现有字节流)
DataOutputStream dos = new DataOutputStream(OutputStream out);
典型初始化方式
java
try (DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("data.bin")))) {
// 写入操作...
}
三、核心方法
方法 | 参数类型 | 作用 |
---|---|---|
writeBoolean(boolean v) | boolean | 写入1字节(true=1, false=0) |
writeByte(int v) | int | 写入低8位(1字节) |
writeShort(int v) | int | 写入低16位(2字节,大端序) |
writeChar(int v) | int | 写入低16位(2字节,作为Unicode字符) |
writeInt(int v) | int | 写入4字节(大端序) |
writeLong(long v) | long | 写入8字节(大端序) |
writeFloat(float v) | float | 写入4字节(IEEE 754标准) |
writeDouble(double v) | double | 写入8字节(IEEE 754标准) |
writeUTF(String str) | String | 写入UTF-8编码字符串(前2字节为长度头) |
writeBytes(String s) | String | 写入字符串的低8位(丢弃高8位) |
writeChars(String s) | String | 写入每个字符的16位(类似writeChar) |
size() | - | 返回已写入的字节数 |
四、工作原理图解
mermaid
sequenceDiagram
participant Program
participant DataOutputStream
participant UnderlyingStream
Program->>DataOutputStream: writeInt(12345)
DataOutputStream->>DataOutputStream: 转换为大端序4字节 [0x00, 0x00, 0x30, 0x39]
DataOutputStream->>UnderlyingStream: 写入字节序列
五、实战代码模板
1. 写入二进制文件
java
try (DataOutputStream dos = new DataOutputStream(
new FileOutputStream("data.bin"))) {
dos.writeInt(2023); // 写入版本号
dos.writeBoolean(true); // 写入标志位
dos.writeDouble(99.95); // 写入价格
dos.writeUTF("Java编程"); // 写入UTF-8字符串
}
2. 与DataInputStream配合
java
// 写入端
try (DataOutputStream dos = new DataOutputStream(...)) {
dos.writeLong(System.currentTimeMillis());
dos.writeUTF("日志内容");
}
// 读取端
try (DataInputStream dis = new DataInputStream(...)) {
long timestamp = dis.readLong();
String message = dis.readUTF();
}
3. 写入原始字符串
java
// 写入ASCII字符串(非UTF-8)
dos.writeBytes("ASCII text"); // 每个字符只写低8位
// 写入Unicode字符串
dos.writeChars("Unicode文本"); // 每个字符写2字节
六、特殊注意事项
1. 字节顺序(Endianness)
-
强制使用大端序(网络字节序),与CPU架构无关
java
// 写入int 0x12345678
// 实际字节序列: [0x12, 0x34, 0x56, 0x78]
2. writeUTF() 规范
-
格式:2字节长度头(最大65535) + UTF-8编码内容
-
与标准UTF-8的区别:修改版UTF-8(null字符用2字节表示)
3. 资源管理
-
必须调用flush():确保缓冲区数据写入磁盘(close()会自动调用)
七、记忆心法
1. 三字经记忆法
"写类型,大端序,配输入"
写类型:支持各种基本数据类型
大端序:固定使用Big-endian
配输入:需配合DataInputStream读取
2. 对比记忆表
对比维度 | DataOutputStream | ObjectOutputStream |
---|---|---|
数据格式 | 简单二进制 | Java对象序列化格式 |
写入方法 | writeInt()/writeUTF()等 | writeObject() |
典型用途 | 自定义二进制协议 | Java对象持久化 |
3. 场景联想
想象快递打包:
-
数据:不同类型的物品
-
DataOutputStream:标准化打包工具(按固定格式装箱)
-
写入方法:按规则放入对应大小的箱子
八、高频面试题
1. 为什么要有size()方法?
java
// 示例:计算CRC校验
DataOutputStream dos = ...;
dos.writeInt(123);
int bytesWritten = dos.size(); // 获取已写入字节数
作用:跟踪已写入数据量(如协议头需要长度字段)
2. writeBytes()和writeUTF()的区别?
方法 | 字符处理 | 长度头 | 适用场景 |
---|---|---|---|
writeBytes() | 只取低8位(ASCII字符) | 无 | 纯ASCII文本 |
writeUTF() | 完整UTF-8编码 | 有 | 含非ASCII字符的文本 |
3. 如何写入小端序数据?
java
// 手动转换字节序
int value = 0x12345678;
dos.writeByte(value & 0xFF);
dos.writeByte((value >> 8) & 0xFF);
dos.writeByte((value >> 16) & 0xFF);
dos.writeByte((value >> 24) & 0xFF);
4. 性能优化建议
-
必须包装缓冲流:
java
new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("data.bin")))
九、终极总结
mermaid
pie
title DataOutputStream核心价值
"类型化写入" : 50
"二进制协议" : 30
"大端序处理" : 20
黄金法则:
"生成二进制数据时,必须确保读取方能按相同顺序和数据类型解析!"