Java – IO流 – FileOutputStream字节输出流
简介
FileOutputStream 是 IO流体系中的字节输出OutputStream的子类,负责 字节流的输出操作,可以把程序中的数据写到本地文件中。
创建输出流
输出流总体的操作步骤有三步:
1.创建字节输出流对象
2.写出数据
3.释放资源
创建对象
创建对象构造方法时,可以传递字符串形式的文件绝对或相对地址,也可以创建一个 File 对象并传入。
// 以字符串形式的绝对或相对路径创建字节流对象,默认清空文件内容再写
public FileOutputStream(String name);
// 是否追加内容式写入数据(数据续写)
public FileOutputStream(String name , boolean append)
// 以File对象形式创建字节流对象,默认清空文件内容再写
public FileOutputStream(File name);
// 是否追加内容式写入数据(数据续写)
public FileOutputStream(File name , boolean append)
注意:
1.参数是字符串表示的路径或者是File对象都可以的
2.如果文件不存在会创建一个新的文件,但是要保证父级文件夹路径是存在的,否则会报出异常
3.如果文件已经存在,则会清空文件,除非调用带有 append 参数的构造函数。
写出数据
// 通过写入单个字节的数据到文件中,int 型参数表示要传入的数据为字符对应的ASCII码,如果不传入 append ,默认会清空文件后再写入
public void write(int b);
public void write(int b, boolean append);
// 通过写入字节流数组的方式到文件中,byte 型数组则为这个数据的byte形式的流,如果不传入 append ,默认会清空文件后再写入
public void write(byte b[])
public void write(byte b[], boolean append);
// 一次写一个字节数组中的部分长度的数据
public void write(byte b[], int off, int len)
注意:
1.wirte方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符。
释放资源
Java在写文件的时候,会对文件进行占用锁定,期间其它程序无法对它进行操作,因此我们对文件操作完成后,应该要对文件进行解锁去除占用。
fos.close();
异常中的处理(普通方式)
FileOutputStream
中,包含了编译时异常,如果调用FileOutputStream
创建构造时,会出现编译错误,需要我们 throws
抛出异常。
同时也可以使用 try...catch
的方式进行处理。
但是 try...catch
中存在两个问题:
问题一:FileOutputStream
找不到文件时会直接抛出异常,try
中一旦出现异常时,会停止执行 try
下面的代码,这使得 close()
关闭流这种方法有可能没有执行到。
try {
// 如果 FileOutputStream 出现异常,后面的代码不会执行
FileOutputStream fos = new FileOutputStream("不存在的文件");
// 这里的代码不会被执行,所以 fos.close() 也不会被执行
fos.close();
}catch (IOException e){
e.printStackTrace();
}finally {
// 如果把 fos.close() 放在这里,则因为作用域的原因,会找不到 fos 对象
fos.close();
}
解决方法是,把 FileOutputStream
创建对象移出 try
作用域外
// 把 FileOutputStream 创建对象移出作用域名,必须初始化为 null,否则 finally 处的 fos.close 会报编译错误
// 原因是,未初始化的对象不能调用 任何 方法
FileOutputStreamfis = null;
try {
// 但因 FileOutputStream本身也有编译异常,所以不能在 try 外面 new
fos = new FileOutputStream("不存在的文件");
// 这里的代码不会被执行,所以 fos.close() 也不会被执行
fos.close();
}catch (IOException e){
e.printStackTrace();
}finally {
// 如果把 fos.close() 放在这里,则因为作用域的原因,会找不到 fos 对象
fos.close();
}
问题二:假如,try
中的 FileOutputStream
创建依然报错,那么 fos 对象依然是null
,这时调用 finally
代码块中的 fos.close()
时,依然会报错
// 把 FileOutputStream 创建对象移出作用域名
FileOutputStream fos = null;
try {
// 但因 FileOutputStream本身也有编译异常,所以不能在 try 外面 new
fos = new FileOutputStream("不存在的文件");
// 这里的代码不会被执行,所以 fos.close() 也不会被执行
fos.close();
}catch (IOException e){
e.printStackTrace();
}finally {
if (fos != null){
fos.close();
}
}
解决方法是:在 调用 close()
方法之前,判断 fos 是否为 null
异常中的处理(JDK7方式)
Java 也发现了普通方法中处理 close()
是比较麻烦的,所以在JDK 7 后,提供一个自动关闭文件接口 AutoCloseable
方法,FileOutputStream
实现了 AutoCloseable
接口,我们不需要手动去调用 close()
方法
用法如下
try(定义字节流1; 定义字节流2) {
fos... 处理逻辑
fos2... 处理逻辑
}catch (IOException e){
}
在JDK7中,try
多出一个小括号,括号中编写定义字节流的方法,多个字节流定义,使用;
进行分割即可。
try(FileOutputStream fos = new FileOutputStream("不存在的路径");
FileOutputStream fos2 = new FileOutputStream("不存在的路径")) {
fos... 处理逻辑
fos2... 处理逻辑
}catch (IOException e){
}
不需要调用 close()
方法
异常中的处理(JDK9方式)
从JDK7的方案来看,确实比较好,但是在 try()
中传入创建方法,使得代码非常长,不利于阅读,在JDK9 中,Java 允许创建方法在try()
代码块外面定义,try()
中传个对象即可。
FileOutputStream fos = new FileOutputStream("不存在的路径");
FileOutputStream fos2 = new FileOutputStream("不存在的路径");
try(fos; fos2) {
fos... 处理逻辑
fos2... 处理逻辑
}catch (IOException e){
}
多个对象,依然使用 ;
分割即可。
换行与续写
换行
在不同的操作系统中,换行符也不一样
1.Windows 中的换行符为 \r\n
2.Linux 中的换行符为 \n
3.MacOS 中的换行符为 \r
在Java中,换行符的问题已经做了优化补全,所以即使使用 \n
也可以实现换行
String wrap = "\r\n";
fos.write(wrap.getBytes());
续写
FileOutputStream 在创建对象中,包含了续写的构造函数
FileOutputStream fos = new FileOutputStream("path", true);
共有 0 条评论