readFully 方法通过 while 循环反复调用 read() 补足字节,精确计数已读量 n,直至填满指定长度或抛 EOFException/IOException,不依赖单次 read 返回值。

readFully 方法通过内部循环调用底层输入流的 read(),持续补足未读完的字节,直到指定长度全部填满,或明确遇到流末尾(抛 EOFException)、I/O 错误(抛 IOException)为止。它不依赖单次 read 的返回值做最终判断,而是主动“兜底”确保完整性。
核心机制:循环读取 + 精确计数
readFully 不是简单调用一次 in.read(b, off, len),而是用 while 循环反复读取,每次只读当前缺多少字节:
- 初始化已读字节数
n = 0 - 循环条件:
n (还没读够) - 每次调用:
count = in.read(b, off + n, len - n),只读剩余所需字节数 - 更新:
n += count;若count == -1(流结束),立即抛EOFException
和普通 read(byte[], ...) 的关键区别
标准 InputStream.read(byte[] b, int off, int len) 可能中途返回(比如只读了 3 字节就因缓冲区暂空而返回),而 readFully 会一直等、一直读,直到满足三者之一:
- 成功写满
len字节 - 流提前结束 → 抛
EOFException(不是静默返回 -1) - 发生 I/O 异常 → 抛
IOException
使用前提与注意事项
要让 readFully 正常工作,需满足几个隐含条件:
- 目标长度必须明确:你得知道要读多少字节(比如协议头规定后续 4 字节是长度字段,再后 N 字节是正文)
- 流不能提前关闭:中途 close() 会导致 IOException
-
数组空间足够:
offset和length必须在数组边界内,否则抛IndexOutOfBoundsException - 阻塞行为合理预期:如果数据确实没来齐(如网络延迟、发送端卡住),readFully 会一直阻塞,直到超时(若底层流支持 timeout)或异常发生
典型适用场景
readFully 的设计初衷就是应对“长度确定但传输可能分片”的情况:
- TCP socket 通信中按协议读固定长度字段(如 4 字节 int 表示消息体长度)
- 解析二进制文件头(如 PNG 文件前 8 字节签名)
- 接收序列化对象前先读取长度字段,再用 readFully 读完整对象字节
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











