最新Java基础系列课程--Day10-IO流文件处理(一)https://developer.aliyun.com/article/1423510
2.5 FileOutputStream写字节
各位同学,前面我们学习了使用FIleInputStream读取文件中的字节数据。然后有同学就迫不及待的想学习往文件中写入数据了。
往文件中写数据需要用到OutputStream下面的一个子类FileOutputStream。写输入的流程如下图所示
使用FileOutputStream往文件中写数据的步骤如下:
第一步:创建FileOutputStream文件字节输出流管道,与目标文件接通。 第二步:调用wirte()方法往文件中写数据 第三步:调用close()方法释放资源
代码如下:
/** * 目标:掌握文件字节输出流FileOutputStream的使用。 */ public class FileOutputStreamTest4 { public static void main(String[] args) throws Exception { // 1、创建一个字节输出流管道与目标文件接通。 // 覆盖管道:覆盖之前的数据 // OutputStream os = // new FileOutputStream("file-io-app/src/itheima04out.txt"); // 追加数据的管道 OutputStream os = new FileOutputStream("file-io-app/src/itheima04out.txt", true); // 2、开始写字节数据出去了 os.write(97); // 97就是一个字节,代表a os.write('b'); // 'b'也是一个字节 // os.write('磊'); // [ooo] 默认只能写出去一个字节 byte[] bytes = "我爱你中国abc".getBytes(); os.write(bytes); os.write(bytes, 0, 15); // 换行符 os.write("\r\n".getBytes()); os.close(); // 关闭流 } }
2.6 字节流复制文件
同学们,我们在前面已经把字节输入流和字节输出流都学习完了。现在我们就可以用这两种流配合起来使用,做一个文件复制的综合案例。
比如:我们要复制一张图片,从磁盘D:/resource/meinv.png
的一个位置,复制到C:/data/meinv.png
位置。
复制文件的思路如下图所示:
1.需要创建一个FileInputStream流与源文件接通,创建FileOutputStream与目标文件接通 2.然后创建一个数组,使用FileInputStream每次读取一个字节数组的数据,存如数组中 3.然后再使用FileOutputStream把字节数组中的有效元素,写入到目标文件中
代码如下:
/** * 目标:使用字节流完成对文件的复制操作。 */ public class CopyTest5 { public static void main(String[] args) throws Exception { // 需求:复制照片。 // 1、创建一个字节输入流管道与源文件接通 InputStream is = new FileInputStream("D:/resource/meinv.png"); // 2、创建一个字节输出流管道与目标文件接通。 OutputStream os = new FileOutputStream("C:/data/meinv.png"); System.out.println(10 / 0); // 3、创建一个字节数组,负责转移字节数据。 byte[] buffer = new byte[1024]; // 1KB. // 4、从字节输入流中读取字节数据,写出去到字节输出流中。读多少写出去多少。 int len; // 记住每次读取了多少个字节。 while ((len = is.read(buffer)) != -1){ os.write(buffer, 0, len); } os.close(); is.close(); System.out.println("复制完成!!"); } }
三、IO流资源释放
各位同学,前面我们已经学习了字节流,也给同学们强调过,流使用完之后一定要释放资源。但是我们之前的代码并不是很专业。
我们现在知道这个问题了,那这个问题怎么解决呢? 在JDK7以前,和JDK7以后分别给出了不同的处理方案。
3.1 JDK7以前的资源释放
在JDK7版本以前,我们可以使用try…catch…finally语句来处理。格式如下
try{ //有可能产生异常的代码 }catch(异常类 e){ //处理异常的代码 }finally{ //释放资源的代码 //finally里面的代码有一个特点,不管异常是否发生,finally里面的代码都会执行。 }
改造上面的低吗:
public class Test2 { public static void main(String[] args) { InputStream is = null; OutputStream os = null; try { System.out.println(10 / 0); // 1、创建一个字节输入流管道与源文件接通 is = new FileInputStream("file-io-app\\src\\itheima03.txt"); // 2、创建一个字节输出流管道与目标文件接通。 os = new FileOutputStream("file-io-app\\src\\itheima03copy.txt"); System.out.println(10 / 0); // 3、创建一个字节数组,负责转移字节数据。 byte[] buffer = new byte[1024]; // 1KB. // 4、从字节输入流中读取字节数据,写出去到字节输出流中。读多少写出去多少。 int len; // 记住每次读取了多少个字节。 while ((len = is.read(buffer)) != -1){ os.write(buffer, 0, len); } System.out.println("复制完成!!"); } catch (IOException e) { e.printStackTrace(); } finally { // 释放资源的操作 try { if(os != null) os.close(); } catch (IOException e) { e.printStackTrace(); } try { if(is != null) is.close(); } catch (IOException e) { e.printStackTrace(); } } } }
代码写到这里,有很多同学就已经看不下去了。是的,我也看不下去,本来几行代码就写完了的,加上try…catch…finally之后代码多了十几行,而且阅读性并不高。难受…
3.2 JDK7以后的资源释放
刚才很多同学已经发现了try…catch…finally处理异常,并释放资源代码比较繁琐。Java在JDK7版本为我们提供了一种简化的是否资源的操作,它会自动释放资源。代码写起来也想当简单。
格式如下:
try(资源对象1; 资源对象2;){ 使用资源的代码 }catch(异常类 e){ 处理异常的代码 } //注意:注意到没有,这里没有释放资源的代码。它会自动释放资源
代码如下:
/** * 目标:掌握释放资源的方式:try-with-resource */ public class Test3 { public static void main(String[] args) { try ( // 1、创建一个字节输入流管道与源文件接通 InputStream is = new FileInputStream("D:/resource/meinv.png"); // 2、创建一个字节输出流管道与目标文件接通。 OutputStream os = new FileOutputStream("C:/data/meinv.png"); ){ // 3、创建一个字节数组,负责转移字节数据。 byte[] buffer = new byte[1024]; // 1KB. // 4、从字节输入流中读取字节数据,写出去到字节输出流中。读多少写出去多少。 int len; // 记住每次读取了多少个字节。 while ((len = is.read(buffer)) != -1){ os.write(buffer, 0, len); } System.out.println(conn); System.out.println("复制完成!!"); } catch (Exception e) { e.printStackTrace(); } } }
四、字符流
同学们,前面我们学习了字节流,使用字节流可以读取文件中的字节数据。但是如果文件中有中文使用字节流来读取,就有可能读到半个汉字的情况,这样会导致乱码。虽然使用读取全部字节的方法不会出现乱码,但是如果文件过大又不太合适。
所以Java专门为我们提供了另外一种流,叫字符流,可以字符流是专门为读取文本数据而生的。
4.1 FileReader类
先类学习字符流中的FileReader类,这是字符输入流,用来将文件中的字符数据读取到程序中来。
FileReader读取文件的步骤如下:
第一步:创建FileReader对象与要读取的源文件接通 第二步:调用read()方法读取文件中的字符 第三步:调用close()方法关闭流
需要用到的方法:先通过构造器创建对象,再通过read方法读取数据(注意:两个read方法的返回值,含义不一样)
/** * 目标:掌握文件字符输入流。 */ public class FileReaderTest1 { public static void main(String[] args) { try ( // 1、创建一个文件字符输入流管道与源文件接通 Reader fr = new FileReader("io-app2\\src\\itheima01.txt"); ){ // 2、一个字符一个字符的读(性能较差) // int c; // 记住每次读取的字符编号。 // while ((c = fr.read()) != -1){ // System.out.print((char) c); // } // 每次读取一个字符的形式,性能肯定是比较差的。 // 3、每次读取多个字符。(性能是比较不错的!) char[] buffer = new char[3]; int len; // 记住每次读取了多少个字符。 while ((len = fr.read(buffer)) != -1){ // 读取多少倒出多少 System.out.print(new String(buffer, 0, len)); } } catch (Exception e) { e.printStackTrace(); } } }
最新Java基础系列课程--Day10-IO流文件处理(三)https://developer.aliyun.com/article/1423512