跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Java DataInputStream
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{Note|本教程适用于Java 8及以上版本。部分特性在早期版本中可能不可用。}} = Java DataInputStream = '''DataInputStream'''是Java I/O体系中一个重要的二进制数据读取类,它属于<code>java.io</code>包,允许以与机器无关的方式从底层输入流中读取原始Java数据类型(如int、float、double等)。它是装饰器模式的典型应用,需要包装其他<code>InputStream</code>实现类使用。 == 核心特性 == * 支持读取Java基本数据类型(<code>readInt()</code>, <code>readDouble()</code>等) * 采用大端字节序(Big-Endian)读取数据 * 实现<code>DataInput</code>接口 * 线程不安全(需外部同步) * 读取方法会阻塞直至数据可用 == 类继承关系 == <mermaid> classDiagram InputStream <|-- FilterInputStream FilterInputStream <|-- DataInputStream DataInput <|.. DataInputStream class InputStream{ <<abstract>> +read() int } class FilterInputStream{ -in: InputStream } class DataInputStream{ +readBoolean() boolean +readInt() int +readUTF() String } class DataInput{ <<interface>> +readBoolean() boolean +readInt() int } </mermaid> == 基础用法 == === 构造方法 === DataInputStream必须包装现有的输入流: <syntaxhighlight lang="java"> // 示例:包装FileInputStream FileInputStream fis = new FileInputStream("data.bin"); DataInputStream dis = new DataInputStream(fis); </syntaxhighlight> === 主要方法 === {| class="wikitable" |- ! 方法签名 !! 返回类型 !! 说明 |- | <code>readBoolean()</code> || boolean || 读取1字节布尔值 |- | <code>readByte()</code> || byte || 读取1字节 |- | <code>readShort()</code> || short || 读取2字节(大端序) |- | <code>readInt()</code> || int || 读取4字节(大端序) |- | <code>readLong()</code> || long || 读取8字节(大端序) |- | <code>readFloat()</code> || float || 读取4字节IEEE 754浮点数 |- | <code>readDouble()</code> || double || 读取8字节IEEE 754浮点数 |- | <code>readUTF()</code> || String || 读取UTF-8编码字符串 |} == 代码示例 == === 基础数据读取 === <syntaxhighlight lang="java"> try (DataInputStream dis = new DataInputStream( new FileInputStream("data.dat"))) { boolean flag = dis.readBoolean(); // 读取1字节布尔值 int count = dis.readInt(); // 读取4字节整数 double price = dis.readDouble(); // 读取8字节浮点数 String desc = dis.readUTF(); // 读取UTF字符串 System.out.printf("Flag: %b, Count: %d, Price: %.2f, Desc: %s%n", flag, count, price, desc); } catch (IOException e) { e.printStackTrace(); } </syntaxhighlight> 假设<code>data.dat</code>由DataOutputStream写入以下内容: <syntaxhighlight lang="java"> true 42 3.1415 "Java数据流" </syntaxhighlight> 输出结果: <pre> Flag: true, Count: 42, Price: 3.14, Desc: Java数据流 </pre> === 读取字节数组 === <syntaxhighlight lang="java"> // 先读取长度,再读取实际数据 int length = dis.readInt(); byte[] buffer = new byte[length]; dis.readFully(buffer); // 确保读取完整数据 </syntaxhighlight> == 高级特性 == === 字节序处理 === DataInputStream始终使用大端序(Big-Endian)读取数据。如果需要处理小端序数据,可通过<code>ByteBuffer</code>转换: <syntaxhighlight lang="java"> int littleEndianInt = ByteBuffer.wrap(bytes) .order(ByteOrder.LITTLE_ENDIAN) .getInt(); </syntaxhighlight> === 性能优化 === 对于高频读取操作,建议添加缓冲层: <syntaxhighlight lang="java"> DataInputStream dis = new DataInputStream( new BufferedInputStream( new FileInputStream("large.dat"))); </syntaxhighlight> === 异常处理 === 读取时可能抛出<code>EOFException</code>(文件结尾)或<code>UTFDataFormatException</code>(UTF字符串格式错误)。推荐使用try-with-resources确保资源释放。 == 实际应用案例 == === 场景:网络协议解析 === 假设需要解析自定义二进制协议: <mermaid> sequenceDiagram participant Client participant Server Client->>Server: 发送协议数据包 Server->>Server: 使用DataInputStream解析 Note right of Server: 1. 读取魔数(4字节)<br/>2. 读取版本号(1字节)<br/>3. 读取负载长度(4字节)<br/>4. 读取实际数据 Server-->>Client: 返回响应 </mermaid> 对应代码实现: <syntaxhighlight lang="java"> public ProtocolPacket parsePacket(InputStream in) throws IOException { DataInputStream dis = new DataInputStream(in); int magicNumber = dis.readInt(); // 协议标识 if (magicNumber != 0xCAFEBABE) { throw new ProtocolException("Invalid magic number"); } byte version = dis.readByte(); // 协议版本 int payloadLength = dis.readInt(); // 数据长度 byte[] payload = new byte[payloadLength]; dis.readFully(payload); // 读取完整负载 return new ProtocolPacket(version, payload); } </syntaxhighlight> == 注意事项 == * 读取顺序必须与写入顺序严格一致 * 字符串处理推荐使用<code>readUTF()</code>而非<code>readChar()</code> * 读取方法会阻塞线程直至数据可用 * 不直接支持随机访问(需结合<code>RandomAccessFile</code>) * 大文件处理时注意内存限制 == 数学原理 == DataInputStream处理浮点数时遵循IEEE 754标准。以<code>readDouble()</code>为例: 读取的8字节转换为double的过程为: <math> \text{value} = (-1)^{\text{sign}} \times 2^{\text{exponent}-1023} \times \left(1 + \sum_{i=1}^{52} \frac{\text{bit}_{52-i}}{2^i}\right) </math> 其中: * 第1位:符号位(0正1负) * 2-12位:指数部分(偏移1023) * 13-64位:尾数部分 == 常见问题 == === Q: 如何判断是否到达文件末尾? === 使用<code>available()</code>方法(返回0表示可能到达结尾),但更可靠的方式是捕获<code>EOFException</code>。 === Q: 为什么读取的数据与写入的不一致? === 常见原因包括: 1. 字节序不匹配 2. 读取/写入顺序不一致 3. 未使用相同的编码方式(特别是字符串) === Q: 如何处理自定义数据结构? === 推荐方案: <syntaxhighlight lang="java"> public record Person(String name, int age) {} Person readPerson(DataInputStream dis) throws IOException { String name = dis.readUTF(); int age = dis.readInt(); return new Person(name, age); } </syntaxhighlight> {{Warning|DataInputStream不提供内置的加密或验证机制,敏感数据传输时应结合加密流(如CipherInputStream)使用。}} == 总结 == DataInputStream是Java二进制数据读取的核心类,其特点包括: * 类型安全的原始数据类型读取 * 与DataOutputStream完美配对 * 适合协议解析和持久化存储 * 需严格保持读写顺序一致性 对于现代Java开发,也可考虑<code>java.nio</code>包中的<code>ByteBuffer</code>作为替代方案,特别是在需要高性能或灵活字节序处理的场景。 [[Category:编程语言]] [[Category:Java]] [[Category:Java IO]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
该页面使用的模板:
模板:Mbox
(
编辑
)
模板:Note
(
编辑
)
模板:Warning
(
编辑
)
模块:Arguments
(
编辑
)
模块:Message box
(
编辑
)
模块:Message box/ambox.css
(
编辑
)
模块:Message box/configuration
(
编辑
)
模块:Yesno
(
编辑
)