DataOutputStream 是 Java 中以平台无关二进制格式写入基本数据类型的类,需配 DataInputStream 按相同顺序读取;writeInt、writeDouble 等方法按大端序、固定长度写入,writeUTF 使用含长度前缀的修改版 UTF-8。

DataOutputStream 是 Java 中用于将基本数据类型(如 int、double、boolean 等)以**平台无关的二进制格式**写入输出流的类;它本身不负责读取,读取需配合 DataInputStream。它的核心价值在于:保证写入的字节序列符合 Java 的标准二进制编码规范(大端序、固定长度),便于跨平台、跨语言(如 C/C++ 按约定解析)或后续用 DataInputStream 准确还原。
写入基本数据类型(用 DataOutputStream)
创建 DataOutputStream 包装一个底层输出流(如 FileOutputStream 或 ByteArrayOutputStream),再调用对应 writeXxx() 方法:
- writeInt(123) → 写入 4 字节大端序 int(0x0000007B)
- writeDouble(3.14) → 写入 8 字节 IEEE 754 双精度浮点数
- writeBoolean(true) → 写入 1 字节(0x01)
- writeUTF("你好") → 先写 2 字节长度,再写 UTF-8 编码字节(注意:不是标准 UTF-16,是 Java 自定义变长格式)
⚠️ 注意:DataOutputStream 不提供 writeChar() 的“字符”语义(它写的是 2 字节 Unicode 码点,但 writeChar('a') 实际写入的是 (char)'a' 的数值(97),即 0x0061),通常更推荐用 writeUTF() 存字符串。
读取对应数据(必须用 DataInputStream)
DataOutputStream 写出的数据,必须由 DataInputStream 按**完全相同的顺序和类型**读取,否则会错位或抛出 EOFException/IOException:
立即学习“Java免费学习笔记(深入)”;
- 若用 writeInt() 写,就必须用 readInt() 读(自动读 4 字节并组装为 int)
- 若先 writeBoolean() 再 writeDouble(),读时也必须先 readBoolean() 再 readDouble()
- readUTF() 会先读 2 字节长度,再按该长度读 UTF-8 字节并解码为 String
✅ 正确示例片段:
// 写
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.bin"))) {
dos.writeInt(42);
dos.writeDouble(2.718);
dos.writeUTF("hello");
}
// 读(顺序、类型严格一致)
try (DataInputStream dis = new DataInputStream(new FileInputStream("data.bin"))) {
int x = dis.readInt(); // 得 42
double y = dis.readDouble(); // 得 2.718
String s = dis.readUTF(); // 得 "hello"
}
关键细节与常见误区
- 不处理编码问题:writeUTF() 是 Java 自定义格式(含长度前缀 + 修改版 UTF-8),和标准 UTF-8 文件不完全兼容;如需通用 UTF-8,应改用 OutputStreamWriter + BufferedWriter
- 无自动类型识别:文件里没有元数据标记“接下来是 int”,全靠你代码逻辑保证读写顺序一致 —— 错一位,后续全乱
- 不支持 null 字符串:writeUTF(null) 会抛 NullPointerException;空字符串 "" 可正常写入(长度 0)
- flush() 和 close() 都重要:writeXXX() 一般不缓冲,但包装的底层流可能有缓冲(如 BufferedOutputStream),记得调用 flush() 或 close() 确保写出
替代方案建议(何时不用 DataOutputStream)
- 需要人可读或跨语言通用 → 用 JSON(Jackson/Gson)或 Protocol Buffers
- 存大量结构化对象且追求性能 → 用 Kryo 或 Java 序列化(注意安全限制)
- 只需简单整数/浮点数组 → 直接用 ByteBuffer(更底层、零拷贝、支持字节序切换)
- 日志或配置 → 用 Properties 或纯文本 + Scanner
它适合小规模、强控制、类型明确、且读写方都用 Java 的二进制协议场景,比如自定义网络协议头、本地缓存简单结构体。


















