1、引入
【1】File类:
封装文件/目录的各种信息,对目录/文件进行操作,但是我们不可以获取到文件/目录中的内容。
【2】引入:IO流:
I/O : Input/Output的缩写,用于处理设备之间的数据的传输。
【3】形象理解:IO流 当做一根 “管”:
【4】IO流的体系结构:
(黄色标记的为重点)
2、 案例:通过java程序完成文件的复制操作
(1)功能分解1:文件 ——> 程序:FileReader
一个字符一个字符的将文件中的内容读取到程序中了:
package test2_Copying_of_files;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;/*** @Auther: zhoulz* @Description: test2_Copying_of_files —— 实现文件的复制* @version: 1.0*/
public class Test1 {public static void main(String[] args) throws IOException {//文件--》程序://1.有一个文件:----》创建一个File类的对象File f = new File("d:\\Test.txt");//2.利用FileReader这个流,这个“管”怼到源文件上去// ---》创建一个FileReader的流的对象FileReader fr = new FileReader(f);//提示要抛出异常,直接往外抛,抛给main函数//3.进行操作“吸”的动作 ---》读取动作//下面的代码我们验证了:如果到了文件的结尾处,那么读取的内容为-1//一共5个字符:"abc老师"/*int n1 = fr.read();int n2 = fr.read();int n3 = fr.read();int n4 = fr.read();int n5 = fr.read();int n6 = fr.read(); //在读一个试试//把读的内容输出System.out.println(n1);System.out.println(n2);System.out.println(n3);System.out.println(n4);System.out.println(n5);System.out.println(n6); //结果 -1*///方式1:/*int n = fr.read();//System.out.println(n); // 97while (n != -1){System.out.println(n);n = fr.read(); //输出并且继续读}*///方式2:int n ;while ((n = fr.read()) != -1){System.out.println(n);System.out.println((char)n);}//4.“管”不用了,就要关闭 ---》关闭流//流,数据库,网络资源,靠jvm本身没有办法帮我们关闭,此时必须程序员手动关闭:fr.close();}
}
想一次性读取五个字符,不够的话下次再读五个字符:
代码示例:
package test2_Copying_of_files;import java.io.File;
import java.io.FileReader;
import java.io.IOException;/*** @Auther: zhoulz* @Description: test2_Copying_of_files —— 一次性读取五个字符* @version: 1.0*/
public class Test1_1 {public static void main(String[] args) throws IOException {//文件--》程序://1.创建一个File类的对象File f = new File("d:\\Test.txt");//2.创建一个FileReader的流的对象FileReader fr = new FileReader(f);//提示要抛出异常,直接往外抛,抛给main函数//3.读取动作//引入一个“快递员的小车”,这个“小车”一次拉5个快递:char[] ch = new char[5]; //缓冲数组int len = fr.read(ch);//一次读取5个:返回值是这个数组中的有效长度//abchello你好老师 —— 文件内容while (len != -1){//System.out.println(len); //输出每次读取的有效长度//错误方式:/*for (int i = 0; i < ch.length; i++) {System.out.println(ch[i]); //会多输出:“o你好”}*///应该:正确方式1:/*for (int i = 0; i < len; i++) {System.out.println(ch[i]); }*///正确方式2:将数组转为String,注意后面要家伙要加上:0,len//String str = new String(ch); //输出结果会和上面的错误方式一样//应该是:String str = new String(ch,0,len);System.out.print(str);len = fr.read(ch);}//4.关闭流fr.close();}
}
(2)功能分解2:程序 ——> 文件:FileWriter
一个字符一个字符的向外输出:
代码示例:
package test2_Copying_of_files;import java.io.File;
import java.io.FileWriter;
import java.io.IOException;/*** @Auther: zhoulz* @Description: test2_Copying_of_files* @version: 1.0*/
public class Test2 {public static void main(String[] args) throws IOException {//1、有个目标文件File f = new File("d:\\demo.txt");//2、FileWriter管怼到文件上去:FileWriter fw = new FileWriter(f); //把目标文件传进来//3、开始动作:输出动作//一个字符一个字符的往外输出:String str = "hello你好";for (int i = 0; i < str.length(); i++) {fw.write(str.charAt(i));}//4、关闭流fw.close();}
}
发现:
如果目标文件不存在的话,那么会自动创建此文件。
如果目标文件存在的话:
new FileWriter(f) 相当于对原文件进行覆盖操作。
new FileWriter(f,false) 相当于对源文件进行覆盖操作。不是追加。
new FileWriter(f,true) 对原来的文件进行追加,而不是覆盖。
利用缓冲数组:向外输出(利用缓冲数组:)
代码示例:
package test2_Copying_of_files;import java.io.File;
import java.io.FileWriter;
import java.io.IOException;/*** @Auther: zhoulz* @Description: test2_Copying_of_files* @version: 1.0*/
public class Test2_2 {public static void main(String[] args) throws IOException {//1、有个目标文件File f = new File("d:\\demo.txt");//2、FileWriter管怼到文件上去:FileWriter fw = new FileWriter(f,true); //把目标文件传进来//3、开始动作:输出动作//一个字符一个字符的往外输出:/*String str = "abc";for (int i = 0; i < str.length(); i++) {fw.write(str.charAt(i));}*/String str = "-万里长城永不倒";char[] chars = str.toCharArray();fw.write(chars);//4、关闭流fw.close();}
}
(3)功能分解3:利用FileReader,FileWriter文件复制
代码示例:
package test2_Copying_of_files;import java.io.*;/*** @Auther: zhoulz* @Description: test2_Copying_of_files* @version: 1.0*/
public class Test3_Copy {public static void main(String[] args) throws IOException {//1、有一个源文件File f1 = new File("d:\\Test.txt");//2、有一个目标文件File f2 = new File("d:\\Demo.txt");//3、搞一个输入的管 怼到源文件上:FileReader fr = new FileReader(f1);//4.搞一个输出的管,怼到目标文件上:FileWriter fw = new FileWriter(f2);//5.开始动作://方式1:一个字符一个字符的复制:/*int n = fr.read();while (n != -1){//System.out.println(n);//System.out.println((char) n);fw.write(n);n = fr.read();}*///方式2:利用缓冲字符数组:/* char[] ch = new char[5];int len = fr.read(ch);while (len != -1){fw.write(ch,0,len); // 0 - len 为有效长度len = fr.read(ch);}*///方式3:利用缓冲字符数组,将数组转为String写出char[] ch = new char[5];int len = fr.read(ch);while (len != -1){//把ch中0-len的有效长度转成字符串String :String s = new String(ch,0,len); // 注意:有效长度//然后直接将字符串写出来fw.write(s);//fw.write(ch,0,len); // 0 - len 为有效长度len = fr.read(ch);}//6.关闭流:(关闭流的时候,倒着关闭,后用先关)fw.close();fr.close();}
}
警告:不要用字符流去操作非文本文件
文本文件:.txt .java .c .cpp —— 建议使用字符流操作;
非文本文件:.jpg、.mp3 , .mp4 , .doc , .ppt —— 建议使用字节流操作。
3、利用try-catch-finally处理异常方式
代码示例:
package test2_Copying_of_files;import java.io.*;/*** @Auther: zhoulz* @Description: test2_Copying_of_files* @version: 1.0*/
public class Test4_Try {public static void main(String[] args) {//1、有一个源文件File f1 = new File("d:\\Test.txt");//2、有一个目标文件File f2 = new File("d:\\Demo.txt");//3、搞一个输入的管 怼到源文件上:// try - catch —— 处理异常FileReader fr = null;//把 fw 也提出来:FileWriter fw = null; //记得初始化try {fr = new FileReader(f1);//后面的代码都剪切进来://4.搞一个输出的管,怼到目标文件上:fw = new FileWriter(f2);//还有异常,继续添加即可//5.开始动作://方式3:char[] ch = new char[5];int len = fr.read(ch);while (len != -1){String s = new String(ch,0,len);fw.write(s);len = fr.read(ch);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {//关闭流的操作一定要放到finally里,因为这里的代码无论如何都会执行//6.关闭流:try { // 上面有可能操作文件失败,则文件为空,关闭空文件—即空指针异常if (fw != null){//防止空指针异常:fw.close(); // fw 报错的原因:作用域的原因}//fr.close();//不能将fr.close();直接拿进来,而是要各自try-catch处理异常} catch (IOException e) {e.printStackTrace();}//各自处理异常,相互不会干扰try {if (fr != null){//防止空指针异常:fr.close();}} catch (IOException e) {e.printStackTrace();}}}
}