FileInputStream 在使用完以后,不关闭流,想二次使用可以怎么操作

文章介绍了Java中IO流的基本使用,包括打开、读取和关闭文件流的过程。然后通过一个示例展示了当尝试重新使用已关闭的FileInputStream时,由于不能再次new,所以使用反射调用private的open方法,从而实现流的复用。最终,通过反射成功读取了文件内容两次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


我们使用IO,都是要先打开:

 //打开流
 FileInputStream fileInputStream = new FileInputStream(new File(fileName));

读写:

 int by = 0;
 byte []bytes = new byte[10];
 //        一个字节数组的读出数据
 while ((by = fileInputStream.read(bytes)) != -1){
     System.out.print((new String(bytes, 0, by)));
 }

使用完毕了就要关闭:

 //关闭流
 fileInputStream.close();


IO的使用大概就是这三个过程。

首先来一个正常的IO完整操作:


我来复现这个操作,我预先在F:\\HelloCoder-HaC.txt 文件写入以下内容:

 HelloCoder ,I am hh
 My webSite is https://blog.csdn.net/qq_42543063

注意这里是FileInputStream,是一个字节流不要出现中文字符否则会乱码
写一下代码:

 public class InputStreamTest {
     public static void main(String[] args) throws IOException {
         String fileName = "F:\\HelloCoder-HaC.txt";
         File file = new File(fileName);
         if (!file.exists()) {
             file.mkdir();
         }
         FileInputStream fileInputStream = new FileInputStream(new File(fileName));
         int by = 0;
         byte[] bytes = new byte[10];
 //        一个字节数组的读出数据
 //        第一次读写        
         while ((by = fileInputStream.read(bytes)) != -1) {
             System.out.print((new String(bytes, 0, by)));
         }
 ​
         //关闭流后如何打开,利用反射
         System.out.println();
         System.out.println("-------重新复用流-------");
 //      第二次 重新读写
         bytes = new byte[10];
         while ((by = fileInputStream.read(bytes)) != -1) {
             System.out.print((new String(bytes, 0, by)));
         }
     }
 }

输出:

 HelloCoder ,I am HaC
 My webSite is https://rain.baimuxym.cn
 -------重新复用流-------
 ​

很明显看到这个第二次的输出是没有任何结果的。

回到问题: 
要重新复用流,那肯定就不能重新new FileInputStream,我想到的是使用反射,如果对反射不熟悉的,建议看一下:

Java的反射是个什么东西???

那反射要实现,需要获取哪个方法呢?我们看一下FileInputStream 的源码:

 public FileInputStream(File file) throws FileNotFoundException {
         String name = (file != null ? file.getPath() : null);
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(name);
         }
         if (name == null) {
             throw new NullPointerException();
         }
         if (file.isInvalid()) {
             throw new FileNotFoundException("Invalid file path");
         }
         fd = new FileDescriptor();
         fd.attach(this);
         path = name;
         open(name);
     }
     private void open(String name) throws FileNotFoundException {
         open0(name);
     }
      /**
      * Opens the specified file for reading.
      * @param name the name of the file
      */
     private native void open0(String name) throws FileNotFoundException;

FileInputStream 在最后会通过open(name) 这个方法打开文件,open()会调用open0(), open0()是一个native方法,实现不是java,看到注释,大概的意思就是指定文件路径,然后可以打开进行读操作。

既然知道open() 方法,那就可以用反射了,注意这个方法是private。

知道方法那就很容易了。

解决:
代码如下:

 

public class InputStreamTest {
     public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
 ​
         String fileName = "F:\\HelloCoder-HaC.txt";
         File file = new File(fileName);
         if (!file.exists()) {
             file.mkdir();
         }
         FileInputStream fileInputStream = new FileInputStream(new File(fileName));
         int by = 0;
         byte[] bytes = new byte[10];
 //        一个字节数组的读出数据
 //        第一次读写  
         while ((by = fileInputStream.read(bytes)) != -1) {
             System.out.print((new String(bytes, 0, by)));
         }
 //        //关闭流,这里关闭也不影响
         fileInputStream.close();
 ​
         //关闭流后如何打开,利用反射
         System.out.println();
         System.out.println("-------重新复用流-------");
 //      第二次 重新读写
         Class in = fileInputStream.getClass();
         Method openo = in.getDeclaredMethod("open", String.class);
         //因为是private
         openo.setAccessible(true);
         openo.invoke(fileInputStream, fileName);
         bytes = new byte[10];
         while ((by = fileInputStream.read(bytes)) != -1) {
             System.out.print((new String(bytes, 0, by)));
         }
     }
 }


输出:

 HelloCoder ,I am HaC
 My webSite is https://rain.baimuxym.cn
 -------重新复用流-------
 HelloCoder ,I am HaC
 My webSite is https://rain.baimuxym.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值