字节流:
在前面的学习过程中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据。现在我们就要开始给文件中写数据,或者读取文件中的数据。
字节输出流 OutputStream:
字节输出流可以操作任何文件,因为它是最小单位 字节来操作的。(一个字节等于8个二进制位)。
OutputStream此抽象类(它直接继承 java.lang.Object),是表示输出字节流的所有类的超类。操作的数据都是字节,它定义了输出字节流的基本共性功能方法。
抽象类 方法概述:
常用的方法是:
write 和 close 。分别用来想文件中写入。和 释放与流 相关的操作系统资源(因为真实的情况,写入到文件中,是程序调用操作系统来完成的,所以写入完毕之后要释放操作系统资源!)
字节输出流 FileOutputStream:
它继承OutputStream。作用是 写入到文件中。
IO这里的类名,命名很有特点,它的后半部分说明的是它继承的父类是谁,它的后半部分说明的是它自己的作用。
对于FileOutputStream来说,它的构造函数中传入的参数是它要将数据存入的文件对象/或文件路径。如果文件不存在,就创建新文件,如果已经有了就直接覆盖掉了。
1 package cn.zcb.demo02; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 6 public class Test{ 7 //FileOutputStream 类的使用 8 public static void main(String[] args) throws IOException { 9 FileOutputStream fostream = new FileOutputStream("d:\a.txt"); 10 //使用fostream.write() 向文件中写 内容。 11 //write() 方法之 write(int a)// 此时是写入一个字节。 12 fostream.write(100);// 100 先作为字节。然后写入。 13 14 fostream.close();//释放操作系统资源 15 } 16 }
1 package cn.zcb.demo02; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 6 public class Test{ 7 //FileOutputStream 类的使用 8 public static void main(String[] args) throws IOException { 9 FileOutputStream fostream = new FileOutputStream("d:\a.txt"); 10 //使用fostream.write() 向文件中写 内容。 11 //write() 方法之 write(int a)// 此时是写入一个字节。 12 fostream.write(100); 13 // 100 变为一个字节: b 0011 1010 然后存入文件。 14 //此时,如果我们打开文件查看,我们看不到二进制,因为在我们看到之前已经进行了转码了。 15 16 17 fostream.close();//释放操作系统资源 18 } 19 }
此时打开文件,会发现里面的是个字符 “d”,因为我们写的100 是一个字节写入的。
但是,我们用编辑器打开一个文件的时候,编辑器都会将里面的内容用编码表进行编码。
对于汉字,如果是GBK编码的话,一个汉字是两个字节。如果是UTF8的话一个汉字是3个字节!
1 package cn.zcb.demo02; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 6 public class Test{ 7 //FileOutputStream 类的使用 8 public static void main(String[] args) throws IOException { 9 FileOutputStream fostream = new FileOutputStream("d:\a.txt"); 10 fostream.write(49); //49 是 '1'的ASCII值 11 fostream.write(48); 12 fostream.write(48); 13 14 fostream.close();//释放操作系统资源 15 } 16 }
1 package cn.zcb.demo02; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 6 public class Test{ 7 //FileOutputStream 类的使用 8 public static void main(String[] args) throws IOException { 9 FileOutputStream fostream = new FileOutputStream("d:\a.txt"); 10 //1,写 一个字节。 write(int a); 11 fostream.write(49); //49 是 '1'的ASCII值 12 fostream.write(97); //97 是 'a' 的ASCII值 13 14 //写入一个字节分隔 15 fostream.write('|');// '|' 先转为int 类型,然后int 转为一个字节,然后存入到文件中。 16 17 //2,写 字节数组 write(byte [] ) 18 byte [] arr = {65,66,67,68}; //'A' 'B' 'C' 'D' 19 fostream.write(arr); 20 21 22 fostream.write('|'); 23 byte [] arr1 = {65,66,67,68}; //byte 的范围 【-128,127】 24 fostream.write(arr1); 25 26 fostream.write('|'); 27 byte [] arr2 = {-65,-66,-67,-68}; 28 fostream.write(arr1,1,2); 29 30 fostream.close();//释放操作系统资源 31 } 32 }
1 package cn.zcb.demo02; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 6 public class Test{ 7 //FileOutputStream 类的使用 8 public static void main(String[] args) throws IOException { 9 10 FileOutputStream f = new FileOutputStream("d:\a.txt"); 11 12 //字节类型的取值为 【 -128 ,- 127】 13 14 f.write("Hello World".getBytes());//写入文件的简便写法。 15 // "Hello world" 先变为字节数组 {72 101 108 108 111 32 87 111 114 108 100 } 然后再写入文件。 16 f.write('|'); 17 18 19 f.write("我爱你中国".getBytes()); 20 //中文 “我爱你中国” 也是先变为 字节数组 如下: 21 //arr = { -26 -120 -111 -25 -120 -79 -28 -67 -96 -28 -72 -83 -27 -101 -67} //UTF8 三个字节一个汉字。 22 // -26 -120 -111 的二进制 分别如下:1110 0110 1000 1000 1001 0001 于是可以推知 汉字"我"的三个字节为:1110 0110 1000 1000 1001 0001 23 24 25 /* 26 //字节类型 的范围 1000 0000(-128) <-- 1111 1111(-1) <-- 0000 0000 --> 0111 1111(127) 注:这种表示都是补码。 27 //1111 1111 28 //0000 0001 29 //正数 的原码,反码,补码都是一样的。那么负数呢? 30 //负数的,要用正数的补码 取反,然后再加1得到负数的补码。计算机中用的 就只是补码。 31 // 1 2 4 8 16 32 64 128 32 byte a = -26; //-26的 补码是:26补码: 0001 1010; 然后取反 1110 0101;然后加一 得到:1110 0110; 故-26补码为:1110 0110 33 byte b = -120; //同理 ,-120 的补码是: 1000 1000 34 byte c = -111; // -111 的补码是: 1001 0001 35 36 /*输出 二进制代表的值 37 byte ret = (byte) 0b10010001; 38 System.out.println(ret); 39 */ 40 41 /* 42 * 如何 查看 我爱你中国 的字节数组表示: 43 byte[] ret = "我爱你中国".getBytes(); 44 for (int i = 0;i<ret.length;i++){ 45 System.out.print(ret[i]+" "); 46 } 47 * */ 48 //不管怎样,FileOutputStream 都是一次一个字节地 写入的。 49 } 50 51 52 53 }
.getBytes() 会返回一个 字节数组,我们直接将其写入即可。
在文件的末尾 继续写:
它只需要在 FileOutputStream的构造方法中的第二个参数,传入true即可。它的那个参数append ,默认是false ,代表不append,如果传入的是true ,就是代表写入文件时不覆盖原文件。
1 package cn.zcb.demo02; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 7 public class Test{ 8 //FileOutputStream 类的使用 字节流(以字节写入) 9 public static void main(String[] args) throws IOException { 10 File file = new File("d:\a.txt"); 11 FileOutputStream fd = new FileOutputStream(file,true); //true代表的意思是 在文件末尾添加内容。 12 13 fd.write("hello".getBytes()); 14 fd.write("我爱你中国".getBytes()); 15 16 fd.close(); //释放系统资源 17 } 18 }
在文件中 写入换行符:
1 package cn.zcb.demo02; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 7 public class Test{ 8 //FileOutputStream 类的使用 字节流(以字节写入) 9 public static void main(String[] args) throws IOException { 10 File file = new File("d:\a.txt"); 11 FileOutputStream fd = new FileOutputStream(file); //覆盖写 12 fd.write("Hello World ".getBytes()); //此时直接写 也是可以的。程序帮我们做了处理的! 13 fd.write("我爱你中国".getBytes()); 14 15 fd.close(); //释放系统资源 16 } 17 }
IO流中的异常处理:
在FileOutputStream类 和 .write() 写入文件的时候,我们总是会遇到编译器 提示,可能会出现 找不到文件异常,和写入文件失败异常。
文件找不到的异常叫做:FileNotFoundException
文件写入失败异常叫做:IOException
二者关系是 FileNotFoundException --> IOException
我们不能总是将异常抛出到JVM中。这里我们就使用try -catch -finally 来处理它。
package cn.zcb.demo02; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Test{ //FileOutputStream 类的使用 字节流(以字节写入) public static void main(String[] args){ /*version 1 try { FileOutputStream fd = new FileOutputStream("d:\a.txt"); fd.write("hello world".getBytes()); }catch (FileNotFoundException e){ System.out.println(e); }catch (IOException e){ System.out.println(e); }finally { fd.close();//这里会报错 ,因为这里访问不到fd ,应该在try 作用域外面声明fd变量,然后再try 中给其赋值,这样在 finally中也就可以使用使用了。 } */ //代码如下:事实有问题 /*version 2 FileOutputStream fd; try { fd = new FileOutputStream("d:\a.txt"); fd.write("hello world".getBytes()); }catch (FileNotFoundException e){ System.out.println(e); }catch (IOException e){ System.out.println(e); }finally { fd.close(); //报错 fd可能 未被初始化。 } */ /*version 3 解决可能为被初始化问题之后,又出错。 FileOutputStream fd = null; try { fd = new FileOutputStream("d:\a.txt"); fd.write("hello world".getBytes()); }catch (FileNotFoundException e){ System.out.println(e); }catch (IOException e){ System.out.println(e); }finally { fd.close(); //报错 可能会产生 IOException 异常。 } */ //version 最终版本。 FileOutputStream fd = null; try { fd = new FileOutputStream("d:\a.txt"); fd.write("hello world".getBytes()); }catch (FileNotFoundException e){ System.out.println(e); throw new RuntimeException("文件写入失败,请重试!!!"); //这种场景是 电脑上差一个u盘,然后程序向u盘写数据,写着写着,我们如果突然拔掉u盘,那么此时的程序是无法继续的。只能重试。告知用户执行失败。这就是 很多硬件的问题,软件(程序)是无法处理的。 }catch (IOException e){ System.out.println(e); }finally { try { fd.close(); //在这里处理异常。 }catch (IOException e){ System.out.println(e); throw new RuntimeException("关闭资源失败。。。"); //也不是没可能,当系统资源崩溃的时候,我们就不能释放系统资源了。 } } } }
还有 在fd.close() 之前最好要 判断是否为null !
字节输入流 InputStream:
读取数据到程序中。
字节输入流 FileInputStream:
它的构造方法:
fd.read()方法:
1 package cn.zcb.demo02; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Test{ 6 //FileInputStream 类的使用 7 public static void main(String[] args) throws IOException { 8 //1 9 FileInputStream fd = new FileInputStream("d:\a.txt"); //a.txt中存储的内容是 abc 10 11 int i= fd.read(); //fd.read() 时,每次都是返回一次字节。 12 System.out.println(i); 13 i = fd.read(); 14 System.out.println(i); 15 i = fd.read(); 16 System.out.println(i); 17 18 i = fd.read(); //此时已经没有数据了。返回-1 19 System.out.println(i); 20 i= fd.read(); 21 System.out.println(i); //还读,还是-1 22 23 24 25 26 //3释放资源 27 fd.close(); 28 } 29 }
1 package cn.zcb.demo02; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Test{ 6 //FileInputStream 类的使用 7 public static void main(String[] args) throws IOException { 8 //1 9 FileInputStream fd = new FileInputStream("d:\a.txt"); //a.txt中存储的内容是 abc 10 11 int temp= 0; 12 //使用循环读取 13 while ((temp = fd.read()) != -1){ 14 System.out.print((char)temp); 15 } 16 //3释放资源 17 fd.close(); 18 } 19 }
fd.read(byte [] )方法:
上面两个问题很重要,
1,数组的作用?
2,函数返回的int 是什么?
答:
1,数组是做为一个传入参数的,读到的字节会放到里面。它起到了缓冲的作用。如果数组大小设置过小,要读好多次,才能全部读入。
2,int 是读取到了多少个有效的字节数。 如果一次read() 的时候,一个字节都没读取到,就返回 -1.即完成了文件的读取。
1 package cn.zcb.demo02; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Test{ 6 //FileInputStream 类的使用 7 public static void main(String[] args) throws IOException { 8 //1 9 FileInputStream fd = new FileInputStream("d:\a.txt"); //a.txt中存储的内容abcde 10 11 byte [] arr =new byte[2]; 12 int ret = fd.read(arr); 13 14 //输出数组中的内容 。。。。 15 System.out.println(new String(arr)); //ab 16 /* 如下的遍历,也可以看到字节数组中的内容 17 for (int i =0;i<arr.length;i++){ 18 System.out.print(arr[i]); //9798 19 } 20 */ 21 //查看函数的返回值 为2 代表读出了几个字节。 22 System.out.println(ret); 23 24 //继续读取 25 ret = fd.read(arr); 26 System.out.println(new String(arr)); //cd 27 System.out.println(ret); //2 28 29 //继续读取 30 ret = fd.read(arr); 31 System.out.println(new String(arr)); //ed 之所以出现ed是因为arr数组没有清空,上次的d没有清楚掉 32 System.out.println(ret); //1 //此时,虽然数组没有读满,但是起码还是读了一个,所以不返回-1 33 34 //如果继续打印 35 ret = fd.read(arr); 36 System.out.println(new String(arr)); //ed ,仍然是上次的结果。 37 System.out.println(ret); //-1 ,此时一个都没读取到,返回 -1 38 39 //3释放资源 40 fd.close(); 41 } 42 }
1 package cn.zcb.demo02; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 import java.util.Arrays; 5 6 public class Test{ 7 //FileInputStream 类的使用 8 public static void main(String[] args) throws IOException { 9 //1 10 FileInputStream fd = new FileInputStream("d:\a.txt"); //a.txt中存储的内容abcde 11 12 byte [] arr =new byte[2]; //1,用来存放读来的数据 传入参数!!! 13 int ret = 0; //2, 函数的返回值 ,用于获取读了多少个字节 和 是否读取完毕。传出参数。 14 while ((ret = fd.read(arr)) != -1 ){ //此时就没有读完。。。 15 System.out.println(new String(arr)); 16 //清空 arr,以免污染下次读取。 17 Arrays.fill(arr,(byte)0); //类似于 C语言中的 memset ,此时就不会出现污染问题了! 18 } 19 //3释放资源 20 fd.close(); 21 } 22 }
不过,我们要注意,一般存放我们读取出来的数组,我们一般设置为1024 个字节。就是一次最多可以放1024个字节。
而且要注意 读取之后要使用Arrays.fill(arr,byte(0)); 将其置空。
文件复制原理:
1 package cn.zcb.demo02; 2 3 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 9 public class Test{ 10 public static void main(String[] args) { 11 //一个字节一个字节的读。 12 try { 13 FileInputStream fdIn = new FileInputStream("d:\a.txt"); //src 14 FileOutputStream fdOut = new FileOutputStream("e:\a.txt");//dest 15 16 int ret = 0; 17 while ((ret = fdIn.read()) != -1){ 18 fdOut.write(ret); 19 } 20 }catch (FileNotFoundException e){ 21 e.printStackTrace(); //此时文件为找到。 22 }catch(IOException e){ 23 e.printStackTrace(); 24 }finally { 25 26 27 } 28 29 } 30 }
1 package cn.zcb.demo02; 2 3 4 import com.sun.source.doctree.ThrowsTree; 5 6 import java.io.FileInputStream; 7 import java.io.FileNotFoundException; 8 import java.io.FileOutputStream; 9 import java.io.IOException; 10 import java.util.PropertyResourceBundle; 11 12 public class Test{ 13 public static void main(String[] args) { 14 //一个字节一个字节的读。 15 FileInputStream fdIn = null; 16 FileOutputStream fdOut = null; 17 try { 18 fdIn = new FileInputStream("d:\a.txt"); //src 19 fdOut = new FileOutputStream("e:\a.txt");//dest 20 21 int ret = 0; 22 while ((ret = fdIn.read()) != -1){ 23 fdOut.write(ret); 24 } 25 }catch (FileNotFoundException e){ 26 e.printStackTrace(); //此时文件未找到。 27 }catch(IOException e){ 28 e.printStackTrace(); //此时文件 发生异常。 29 }finally { 30 try { 31 if(fdOut != null) //先开后关!!! 32 fdOut.close(); 33 }catch (IOException e){ 34 e.printStackTrace(); 35 }finally { 36 try{ 37 if(fdIn != null) 38 fdIn.close(); 39 }catch (IOException e){ 40 e.printStackTrace(); 41 } 42 } 43 } 44 } 45 }
但是,上面的代码是很低效的,因为它是读入一个字节,然后又读出到文件中。
下面用字节数组做缓冲,来提高效率!!!
1 package cn.zcb.demo02; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.util.Arrays; 8 9 public class Test{ 10 public static void main(String[] args) { 11 //一个字节一个字节的读。 12 FileInputStream fdIn = null; 13 FileOutputStream fdOut = null; 14 try { 15 fdIn = new FileInputStream("d:\shipin.mp4"); //src 16 fdOut = new FileOutputStream("e:\shipin.mp4");//dest 17 18 int ret = 0; 19 byte [] arr = new byte[1024]; //一次读取 1M 20 while ((ret = fdIn.read(arr)) != -1){ 21 fdOut.write(arr); 22 //arr 置空 23 Arrays.fill(arr,(byte)0); 24 } 25 }catch (FileNotFoundException e){ 26 e.printStackTrace(); //此时文件未找到。 27 }catch(IOException e){ 28 e.printStackTrace(); //此时文件 发生异常。 29 }finally { 30 try { 31 if(fdOut != null) //先开后关!!! 32 fdOut.close(); 33 }catch (IOException e){ 34 e.printStackTrace(); 35 }finally { 36 try{ 37 if(fdIn != null) 38 fdIn.close(); 39 }catch (IOException e){ 40 e.printStackTrace(); 41 } 42 } 43 } 44 } 45 }
1M = 1024K = 1024*1024字节。
对于10M的文件,
如果用一次读一字节,写一字节。那么程序循环要执行 10*1024*1024 次。
而如果使用一次读1024字节,写1024字节。那么程序循环只需要执行10*1024次!
编码表:
为了操作字符流,我们需要知道编码表。
我们知道计算机底层数据存储的都是二进制数据,而我们生活中的各种各样的数据,如何才能和计算机中存储的二进制数据对应起来呢?
这时老美他们就把每一个字符和一个整数对应起来,就形成了一张编码表,老美他们的编码表就是ASCII表。其中就是各种英文字符对应的编码。
编码表:其实就是生活中字符和计算机二进制的对应关系表。
1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx
2、iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx 负数。
3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数
GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,两个字节第一个字节是负数,第二个字节可能是正数
GB18030:最新的中文码表,目前还没有正式使用。
4,unicode:国际标准码表:无论是什么文字,都用两个字节存储。
l Java中的char类型用的就是这个码表。char c = 'a';占两个字节。
l Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。
5、UTF-8:基于unicode,不定长字节。一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。
能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。
对于我们开发而言;常见的编码 GBK UTF-8 ISO-8859-1
文字--->(数字) :编码。 “abc”.getBytes() byte[]
(数字)--->文字 : 解码。 byte[] b={97,98,99} new String(b)
流对象的另一种---字符流:
字符流只能写字符。所以它用于文本处理!
而上面的字节流则可以处理图片,视频啊,等等。
字符输出流 Writer:
字符输出流 Writer学习 ---FileWriter(Writer超类的已知子类):
1 package cn.zcb.demo02; 2 3 import java.io.FileWriter; 4 import java.io.IOException; 5 6 public class Test{ 7 public static void main(String[] args) throws IOException { 8 //FileWriter 学习 9 FileWriter fd = new FileWriter("d:\a.txt"); 10 11 //1, 写1个字符。 12 /* 13 fd.write(100);//'a' 14 fd.flush(); //不然的话,看不见。 15 */ 16 17 /* 18 //2, 写1个字符数组 19 char [] arr = {'a','b','c','d','e'}; 20 fd.write(arr); 21 fd.flush(); 22 23 //2,写1个字符数组的部分 24 fd.write(arr,1,3); //从偏移量0 开始写入3个字符。 25 fd.flush(); 26 */ 27 28 //3,写字符串 29 fd.write("tom hello world"); 30 fd.flush(); 31 32 fd.close(); //.close()暗含 .flush() 33 } 34 }
字符输入流:
字符输入流 Reader学习 ---FileReader(Reader超类的已知子类):
1 package cn.zcb.demo02; 2 3 import java.io.FileReader; 4 import java.io.IOException; 5 6 public class Test{ 7 public static void main(String[] args) throws IOException { 8 //FileReader 学习 9 FileReader fd = new FileReader("d:\a.txt"); //读中文也是可以的。 10 11 //1,一次读入一个字符 12 /**/ 13 int ret = 0; 14 while ((ret = fd.read()) != -1){ 15 System.out.print((char)ret); 16 } 17 18 fd.close(); 19 } 20 }
如果想要读入一个中文文件,也想看到结果的,建议不要使用字节流,使用字符流。
Reader是可以处理中文的。
1 package cn.zcb.demo02; 2 3 import java.io.FileReader; 4 import java.io.IOException; 5 import java.util.Arrays; 6 7 public class Test{ 8 public static void main(String[] args) throws IOException { 9 //FileReader 学习 10 FileReader fd = new FileReader("d:\a.txt"); //读中文也是可以的。 11 12 //1,一次读入一个字符 13 /* 14 int ret = 0; 15 while ((ret = fd.read()) != -1){ 16 System.out.print((char)ret); 17 } 18 */ 19 20 //2,一次读入一个字符数组 21 char [] arr = new char[1024]; 22 int ret = 0; 23 while ((ret = fd.read(arr)) != -1){ 24 System.out.println(new String(arr)); 25 //置空 arr 26 Arrays.fill(arr,'0'); 27 } 28 29 30 31 32 fd.close(); 33 } 34 }
flush() 和 close() 的区别:
flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。而且它只有在写文件(字符流,字节流)时候使用。
close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。
字符流复制 文本文件:
注:字符流只能处理字符。
1 package cn.zcb.demo02; 2 3 4 import java.io.*; 5 import java.util.Arrays; 6 7 public class Test{ 8 public static void main(String[] args) throws IOException { 9 // 注,它只能读 字符。 只能处理文本!!! 10 FileWriter fdWr = null; 11 FileReader fdRd = null; 12 try { 13 fdRd = new FileReader("d:\a.txt"); 14 fdWr= new FileWriter("e:\dest.txt"); 15 16 int ret = 0; 17 char [] arr = new char[1024]; //一次读取 2K 一个字符2个字节。 18 while ((ret = fdRd.read(arr)) != -1){ 19 fdWr.write(arr); 20 //arr 置空 21 Arrays.fill(arr,'0'); 22 } 23 }catch (FileNotFoundException e){ 24 e.printStackTrace(); //此时文件未找到。 25 }catch(IOException e){ 26 e.printStackTrace(); //此时文件 发生异常。 27 }finally { 28 try { 29 if(fdWr != null) //先开后关!!! 30 fdWr.close(); 31 }catch (IOException e){ 32 e.printStackTrace(); 33 }finally { 34 try{ 35 if(fdRd != null) 36 fdRd.close(); 37 }catch (IOException e){ 38 e.printStackTrace(); 39 } 40 } 41 } 42 } 43 }