HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
随笔
关于作者
  • 《LearnJavaToFindAJob》

    • 导读

    • 【初级】6~12k档

    • 【中级】12k-26k档

    • 【高级】26k+档

    • 大厂面试题

      • IBM面试题-不借助变量交换两个数
      • 奇怪的面试题
      • 快手

      • 美团

      • 腾讯

      • 阿里

        • 判断有攻击嫌疑的IP
        • 蚂蚁二面MQ消费端遇到瓶颈除了横向扩容外还有其他解决办法
        • 阿里一面,给了几条SQL,问需要执行几次树搜索操作?
        • 阿里面试真题NIO为什么不适合文件上传场景、如何优雅解决
        • 阿里面试题-FileInputStream在使用完以后,不关闭流,想二次使用可以怎么操作
        • 阿里面试题
    • 求职建议

    • 面经

  • LearnJavaToFindAJob
  • 大厂面试题
  • 阿里
#FileInputStream #阿里面试题
码农阿雨
2022-06-02
目录

阿里面试题-FileInputStream在使用完以后,不关闭流,想二次使用可以怎么操作

# 题目

这道题是在网上看到的,据说是阿里的面试题,真假不知道,但是挺有意思的,大概意思是这样的:

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

我这里简单解释一下这个题目的意思,我们使用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 HaC
My webSite is https://rain.baimuxym.cn

注意这里是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的反射是个什么东西??? (opens new window)

那反射要实现,需要获取哪个方法呢?我们看一下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

以上。

这个面试题真的是妙啊~

不但考察了你对IO的理解,还考察了反射的用法。

大概率还会一步一步来引申以下问题:

  • IO的分类和结构
  • flush方法的作用
  • BIO和NIO的区别
  • 什么是反射
阅读全文
×

(为防止恶意爬虫)
扫码或搜索:HelloCoder
发送:290992
即可永久解锁本站全部文章

解锁
#FileInputStream#阿里面试题
上次更新: 2025-02-21 06:04:57
最近更新
01
《LeetCode 101》
02-21
02
IDEA、Golang、Pycharm破解安装
02-21
03
《LeetCode CookBook》
02-21
更多文章>
Theme by Vdoing | Copyright © 2020-2025 码农阿雨
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式