readNBytes(len) 最多读取 len 字节,不足时返回实际读到的字节数组(含空数组),不补零、不阻塞、不因读不满抛异常;需严格读满时应使用自定义 readFully 方法。
InputStream.readNBytes(int len) 方法会尝试读取恰好 len 个字节,返回长度为 len 的字节数组;如果流提前结束(如到达 EOF),则返回实际读到的字节数组(长度 len),**不会补零或阻塞等待**。它不保证“一定读满”,但行为明确:要么读够,要么读完就停。
这个方法不是“强制读满 len 字节”,而是“最多读 len 字节”,且在流关闭或不可用时立即返回已读内容。它的设计目标是**简洁安全地读取一段数据,避免手动循环和异常处理**,但不适用于必须严格读满的协议场景。
如果业务逻辑要求必须拿到 exactly len 字节(比如解析固定头、解密块、网络协议帧),不能直接依赖 readNBytes(len),而应封装一个阻塞式读取工具方法:
public static byte[] readFully(InputStream in, int len) throws IOException { byte[] buf = new byte[len]; int total = 0; while (total < len) { int n = in.read(buf, total, len - total); if (n == -1) { throw new EOFException("Unexpected end of stream: expected " + len + " bytes, got " + total); } total += n; } return buf;}
这个方法会持续调用 read(byte[], off, len),直到填满整个数组,或遇到真实 EOF 抛出 EOFException。
立即学习“Java免费学习笔记(深入)”;
readAllBytes() 再切片,但注意内存开销适合场景:
– 读取一个“尽力而为”的快照(如日志片段、临时缓存)
– 解析变长但有长度前缀的结构(先读4字节长度,再用 readNBytes(长度))
– 单元测试中模拟小段输入,逻辑不依赖严格字节数
不适合场景:
– TCP 协议中固定 8 字节 header 必须完整
– AES-CBC 解密要求块大小严格对齐
– 文件格式校验需逐字段比对长度