Java InputStream.read() 为什么返回 int?

Java InputStream.read() 为什么返回 int?

InputStream.read() 返回 int,因为它既要表示 0..255 的字节值,也要用 -1 表示 EOF;若返回 byte,0xFF 也会被误判为结束,导致数据丢失。

一个返回值,要装下两类信息

Java 的 byte 是 8 位有符号类型,范围是 -128 到 127。但文件或网络流里的一个字节有 256 种取值:0x00 到 0xFF。InputStream.read() 将读到的字节按无符号值返回为 0 到 255,并把范围之外的 -1 留作"已经到末尾"的标记。

因此正确的单字节读取方式是先用 int 判断 EOF:

java 复制代码
static void readBytes(Path path) throws IOException {
    try (InputStream in = Files.newInputStream(path)) {
        int value;
        while ((value = in.read()) != -1) {
            // value 一定在 0..255 之间
            consume(value);
        }
    }
}

如果先转成 byte 再判断,问题就出现了:

java 复制代码
int value = in.read();
byte b = (byte) value;

当读到 0xFF 时,value 是 255,但转成 byte 后 b 是 -1。如果在转换前没有检查 value == -1,合法数据和 EOF 就会混在一起。需要保留字节数组时,可以在确认不是 EOF 后再转型。

复制文件时,判断的是"本次读到多少"

复制图片、压缩包等二进制内容,通常用缓冲区,而不是每次只读一个字节:

java 复制代码
static void copy(Path source, Path target) throws IOException {
    try (InputStream in = Files.newInputStream(source);
         OutputStream out = Files.newOutputStream(target)) {
        byte[] buffer = new byte[8192];
        int count;

        while ((count = in.read(buffer)) != -1) {
            out.write(buffer, 0, count);
        }
    }
}

这里 count 表示本次实际读入的字节数。一次 read(buffer) 不保证填满整个数组,可能只返回一部分;只有返回 -1 才表示后面没有数据。因此不要用"读到的长度等于缓冲区长度"判断是否结束,也不要只调用一次就认为整个文件已经读完。

字节流和字符流的 read() 不要混为一谈

InputStream.read() 面向字节,返回 0..255 或 -1。字符流 Reader.read() 面向字符,返回 0..65535 的字符值或 -1。两者都用 int,是因为返回类型还要容纳 EOF 标记;但表示的数据单位不同。

如果处理的是文本,应使用 Reader 或 InputStreamReader 并明确字符集。不要把每个字节直接强转成 char 来解码 UTF-8 等多字节编码。

**记住这三点:**单字节读取先用 int 判断 -1;缓冲区读取按返回的实际字节数写出;文本解码交给字符流和明确的字符集。

参考:Java SE 21 InputStream.read() 文档、Java SE 21 Reader.read() 文档。

相关推荐
金銀銅鐵2 小时前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
吴名氏.4 小时前
Java转AI Agent教程(第十三周)混合检索与重排
java·数据库·人工智能·ai·ai agent
.痞老板.5 小时前
java ee--多线程(进阶)
java·java-ee
深入云栈6 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
wang_shu_mo_ran7 小时前
MyBatis 从入门到进阶(一)
java·spring·mybatis
量化分析码农9 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端
猫猫不是喵喵.9 小时前
从0到1创建一个微服务项目
java·数据库·微服务·1024程序员节
瑞雪兆丰年兮9 小时前
JavaWeb-day13-SpringBootWeb事务管理&AOP
java·开发语言·springboot·javaweb·事务·web·aop
曲径海盗9 小时前
Try-Except怎么用,3个追问解答在自动化下的应用
java·jvm·oracle
Cosolar10 小时前
极简智库:快速搭建你的开源项目教程阅读平台,让 docs/ 目录被更多人看见
java·架构·github