在Java的IO体系中,FileInputStream是用于读取文件字节流的常用类,它提供的available方法可以返回当前流中剩余的可读字节总数,这个特性在很多需要预估读取内容的场景中非常实用。不过该方法的行为和很多开发者的预期存在偏差,需要结合具体原理来正确使用。

available方法的基本定义
FileInputStream继承自InputStream,available方法是InputStream中定义的方法,在FileInputStream中做了针对性的实现。该方法的返回值表示当前可以不受阻塞地从这个输入流中读取的剩余字节数。需要注意的是,这里的剩余字节数不一定等于文件的总大小,尤其是在流已经被部分读取的情况下。
方法签名
available方法的签名如下:
public int available() throws IOException
该方法会抛出IOException,当输入流被关闭或者发生其他IO错误时就会触发这个异常。
基础使用示例
下面通过一个简单的示例来演示如何使用available方法查看流中剩余的可读字节总数。首先准备一个测试文件,内容为"hello world",共11个字节。
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamAvailableDemo {
public static void main(String[] args) {
// 文件路径替换为实际测试文件的路径
String filePath = "test.txt";
try (FileInputStream fis = new FileInputStream(filePath)) {
// 第一次调用available,此时还未读取任何内容
int available1 = fis.available();
System.out.println("初始剩余可读字节数:" + available1);
// 读取3个字节
byte[] buffer = new byte[3];
int readCount = fis.read(buffer);
System.out.println("本次读取字节数:" + readCount);
// 再次调用available,查看剩余可读字节数
int available2 = fis.available();
System.out.println("读取3字节后剩余可读字节数:" + available2);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行上述代码,输出结果如下:
初始剩余可读字节数:11 本次读取字节数:3 读取3字节后剩余可读字节数:8
可以看到,初始状态下available返回的是文件的总字节数,读取3个字节之后,剩余可读字节数变为8,符合预期。
available方法的局限性
虽然available方法可以返回剩余可读字节数,但它并不是在所有场景下都能准确反映剩余内容的大小,主要有以下几个局限性:
- 返回值类型是int,最大只能表示2147483647,也就是约2GB,如果文件大小超过这个值,available方法无法返回正确的总字节数。
- 对于网络流或者其他非文件类的输入流,available方法返回的只是当前可以立即读取的字节数,不代表流的总长度,因为后续数据可能还在传输中。
- 如果流已经被关闭,再调用available方法会直接抛出IOException。
常见使用误区
很多开发者会误以为可以用available方法的返回值来创建刚好容纳所有剩余内容的字节数组,比如下面的写法:
try (FileInputStream fis = new FileInputStream("test.txt")) {
// 错误用法:假设available返回的就是所有剩余内容的大小
byte[] data = new byte[fis.available()];
fis.read(data);
System.out.println(new String(data));
} catch (IOException e) {
e.printStackTrace();
}
这种写法在文件较小且流未被部分读取的情况下可能可以正常工作,但存在两个问题:首先read方法不一定能一次性读取完数组长度的内容,可能只读取了部分字节就返回了;其次如果文件大小超过int的最大值,available的返回值会溢出,导致数组创建异常。正确的做法应该是循环读取,或者使用readAllBytes方法(Java 9及以上版本支持)。
正确的使用场景
available方法更适合用在以下场景:
- 需要预估读取操作的耗时,比如剩余字节数较少时可以一次性读取,较多时采用分段读取。
- 在读取前判断流中是否还有内容可读,当available返回0时,说明当前没有可立即读取的字节,但需要注意对于网络流来说,返回0不代表流已经结束。
- 配合read方法使用,避免创建过大的字节数组,比如根据available的返回值决定每次读取的缓冲区大小。
总结
FileInputStream的available方法可以返回当前流中剩余的可读字节总数,但是它的返回值含义和适用场景有明确限制,不能简单地认为它等于文件的总大小。在实际使用中,需要结合流的读取状态、流的类型来判断返回值的意义,避免陷入使用误区。如果需要读取完整的文件内容,更推荐使用循环读取或者Java 9及以上提供的readAllBytes方法,保证读取的完整性和正确性。
FileInputStreamavailable字节流IO流修改时间:2026-06-20 01:03:28