Java – IO流 – FileInputStream字节输入流
简介
操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来。
创建输入流
1.创建字节输入流对象
2.读数据
3.释放资源
创建对象
// 以字符串形式表达文件目录位置
public FileInputStream(String name);
// 以File 对象的形式表达文件目录位置
public FileInputStream(File name);
注意:如果文件不存在或路径不正确,会直接报错异常。
读取数据
// 读取一个字节的数据,返回 int 型,以ASCII码转出,每调用一次就读取一个字节,如果已经读到文件尾,会返回 -1
public int read();
// 一次读取多个字节的数据,返回 int 型,返回的数据为读取的数据长度,
读取的多个字节数据会存到数组中,一次读取多少字节,全看这个 byte[] 数组声明
了多少个成员
// 每一次的read 读取中,都会尽可能的覆盖填满 byte[] 字节数组,但如果到了文件
末尾时,数据存不满,那么上一次填充的数据中,有可能依然还在,因此要注意最后
一次读取时的数据处理。
public int read(byte[] b);
FileInputStream 循环读取
FileInputStream fis = new FileInputStream("Learn\\src\\a.txt");
int b;
while ((b = fis.read()) != -1) {
System.out.println((char) b);
}
释放资源
Java在读文件的时候,会对文件进行占用锁定,期间其它程序无法对它进行操作,因此我们对文件操作完成后,应该要对文件进行解锁去除占用。
fis.close();
异常中的处理(普通方式)
FileInputStream
中,包含了编译时异常,如果调用FileInputStream
创建构造时,会出现编译错误,需要我们 throws
抛出异常。
同时也可以使用 try...catch
的方式进行处理。
但是 try...catch
中存在两个问题:
问题一:FileInputStream
找不到文件时会直接抛出异常,try
中一旦出现异常时,会停止执行 try
下面的代码,这使得 close()
关闭流这种方法有可能没有执行到。
try {
// 如果 FileInputStream 出现异常,后面的代码不会执行
FileInputStream fis = new FileInputStream("不存在的文件");
// 这里的代码不会被执行,所以 fis.close() 也不会被执行
fis.close();
}catch (IOException e){
e.printStackTrace();
}finally {
// 如果把 fis.close() 放在这里,则因为作用域的原因,会找不到 fis 对象
fis.close();
}
解决方法是,把 FileInputStream
创建对象移出 try
作用域外
// 把 FileInputStream 创建对象移出作用域名,必须初始化为 null,否则 finally 处的 fis.close 会报编译错误
// 原因是,未初始化的对象不能调用 任何 方法
FileInputStream fis = null;
try {
// 但因 FileInputStream 本身也有编译异常,所以不能在 try 外面 new
fis = new FileInputStream("不存在的文件");
// 这里的代码不会被执行,所以 fis.close() 也不会被执行
fis.close();
}catch (IOException e){
e.printStackTrace();
}finally {
// 如果把 fis.close() 放在这里,则因为作用域的原因,会找不到 fis 对象
fis.close();
}
问题二:假如,try
中的 FileInputStream
创建依然报错,那么 fis 对象依然是null
,这时调用 finally
代码块中的 fis.close()
时,依然会报错
// 把 FileInputStream 创建对象移出作用域名
FileInputStream fis = null;
try {
// 但因 FileInputStream 本身也有编译异常,所以不能在 try 外面 new
fis = new FileInputStream("不存在的文件");
// 这里的代码不会被执行,所以 fis.close() 也不会被执行
fis.close();
}catch (IOException e){
e.printStackTrace();
}finally {
if (fis != null){
fis.close();
}
}
解决方法是:在 调用 close()
方法之前,判断 fis 是否为 null
异常中的处理(JDK7方式)
Java 也发现了普通方法中处理 close()
是比较麻烦的,所以在JDK 7 后,提供一个自动关闭文件接口 AutoCloseable
方法,FileInputStream
实现了 AutoCloseable
接口,我们不需要手动去调用 close()
方法
用法如下
try(定义字节流1; 定义字节流2) {
fis... 处理逻辑
fis2... 处理逻辑
}catch (IOException e){
}
在JDK7中,try
多出一个小括号,括号中编写定义字节流的方法,多个字节流定义,使用;
进行分割即可。
try(FileInputStream fis = new FileInputStream("不存在的路径");
FileInputStream fis2 = new FileInputStream("不存在的路径")) {
fis... 处理逻辑
fis2... 处理逻辑
}catch (IOException e){
}
不需要调用 close()
方法
异常中的处理(JDK9方式)
从JDK7的方案来看,确实比较好,但是在 try()
中传入创建方法,使得代码非常长,不利于阅读,在JDK9 中,Java 允许创建方法在try()
代码块外面定义,try()
中传个对象即可。
FileInputStream fis = new FileInputStream("不存在的路径");
FileInputStream fis2 = new FileInputStream("不存在的路径");
try(fis; fis2) {
fis... 处理逻辑
fis2... 处理逻辑
}catch (IOException e){
}
多个对象,依然使用 ;
分割即可。
示例:复制文件(小文件)
public static void copySmallFile(String src, String to) throws IOException {
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(to);
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
fos.close();
fis.close();
}
示例:复制文件(大文件)
public static void copySmallFile(String src, String to) throws IOException {
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(to);
int len;
byte[] data = new byte[1024 * 1024 * 10];
while ((len = fis.read(data)) != -1) {
// 使用 write() 带偏移参数的方法,读取相对长度的字节
// 处理当文件读取到末尾时数据填不满byte[]数组读取溢出的问题
fos.write(data, 0, len);
}
fos.close();
fis.close();
}
共有 0 条评论