阿里面试题-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的区别
- 什么是反射
上次更新: 2025-02-21 06:04:57