File类
引入
【1】文件,目录:
文件:
内存中存放的数据在计算机关机后就会消失。要长久保存数据,就要使用硬盘、光盘、U 盘等设备。为了便于数据的管理和检索,引入了“文件”的概念。一篇文章、一段视频、一个可执行程序,都可以被保存为一个文件,并赋予一个文件名。操作系统以文件为单位管理磁盘中的数据。
一般来说,文件可分为文本文件、视频文件、音频文件、图像文件、可执行文件等多种类别,这是从文件的功能进行分类的。从数据存储的角度来说,所有的文件本质上都是一样的,都是由一个个字节组成的,归根到底都是 0、1 比特串。不同的文件呈现出不同的形态(有的是文本,有的是视频等等)
文件夹(目录):
成千上万个文件如果不加分类放在一起,用户使用起来显然非常不便,因此又引入了树形目录(目录也叫文件夹)的机制,可以把文件放在不同的文件夹中,文件夹中还可以嵌套文件夹,这就便于用户对文件进行管理和使用
【2】查看文件/目录的信息:
右键-属性
【3】在java程序中操纵 文件/目录 ?怎么办?
java程序,最典型的特点,面向对象,java程序最擅长的就是操作对象,盘符上的文件/目录,将它的各种信息进行了封装,封装为一个对象,
java程序最擅长的就是操纵对象,这个对象属于 ---》File类
盘符上的文件---》封装为对象---》对象属于File类的对象--》有了这个对象,我们程序就可以直接操纵这个对象,通过这个对象获取文件的各种信息,还可以对文件进行创建 ,删除。
对文件进行操作
1.package com.msb.file;
2.
3.import java.io.File;
4.import java.io.IOException;
5.
6./**
7. * @author : msb-zhaoss
8. */
9.public class Test01 {
10. //这是一个main方法,是程序的入口:
11. public static void main(String[] args) throws IOException {
12. //将文件封装为一个File类的对象:
13. File f = new File("d:\\test.txt");
14. File f1 = new File("d:\\test.txt");
15. File f2 = new File("d:/test.txt");
16. //File.separator属性帮我们获取当前操作系统的路径拼接符号
17. //在windows,dos下,系统默认用“\”作为路径分隔符 ,在unix,url中,使用“/”作为路径分隔符。
18. File f3 = new File("d:"+File.separator+"test.txt");//建议使用这种
19.
20. //常用方法:
21. System.out.println("文件是否可读:"+f.canRead());
22. System.out.println("文件是否可写:"+f.canWrite());
23. System.out.println("文件的名字:"+f.getName());
24. System.out.println("上级目录:"+f.getParent());
25. System.out.println("是否是一个目录:"+f.isDirectory());
26. System.out.println("是否是一个文件:"+f.isFile());
27. System.out.println("是否隐藏:"+f.isHidden());
28. System.out.println("文件的大小:"+f.length());
29. System.out.println("是否存在:"+f.exists());
30. /*if(f.exists()){//如果文件存在,将文件删除操作
31. f.delete();
32. }else{//如果不存在,就创建这个文件
33. f.createNewFile();
34. }*/
35. System.out.println(f == f1);//比较两个对象的地址
36. System.out.println(f.equals(f1));//比较两个对象对应的文件的路径
37.
38. //跟路径相关的:
39. System.out.println("绝对路径:"+f.getAbsolutePath());
40. System.out.println("相对路径:"+f.getPath());
41. System.out.println("toString:"+f.toString());
42.
43. System.out.println("----------------------");
44. File f5 = new File("demo.txt");
45. if(!f5.exists()){
46. f5.createNewFile();
47. }
48. //绝对路径指的就是:真实的一个精准的,完整的路径
49. System.out.println("绝对路径:"+f5.getAbsolutePath());
50. //相对路径:有一个参照物,相对这个参照物的路径。
51. //在main方法中,相对位置指的就是:D:\IDEA_workspace\TestJavaSE
52. //在junit的测试方法中,相对路径指的就是模块位置
53. System.out.println("相对路径:"+f5.getPath());
54. //toString的效果永远是 相对路径
55. System.out.println("toString:"+f5.toString());
56.
57. File f6 = new File("a/b/c/demo.txt");
58. if(!f5.exists()){
59. f5.createNewFile();
60. }
61. System.out.println("绝对路径:"+f6.getAbsolutePath());
62. System.out.println("相对路径:"+f6.getPath());
63. }
64.}
对目录进行操作
1.package com.msb.file;
2.
3.import java.io.File;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test02 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) {
11. //将目录封装为File类的对象:
12. File f = new File("D:\\IDEA_workspace");
13. System.out.println("文件是否可读:"+f.canRead());
14. System.out.println("文件是否可写:"+f.canWrite());
15. System.out.println("文件的名字:"+f.getName());
16. System.out.println("上级目录:"+f.getParent());
17. System.out.println("是否是一个目录:"+f.isDirectory());
18. System.out.println("是否是一个文件:"+f.isFile());
19. System.out.println("是否隐藏:"+f.isHidden());
20. System.out.println("文件的大小:"+f.length());
21. System.out.println("是否存在:"+f.exists());
22. System.out.println("绝对路径:"+f.getAbsolutePath());
23. System.out.println("相对路径:"+f.getPath());
24. System.out.println("toString:"+f.toString());
25.
26. //跟目录相关的方法:
27. File f2 = new File("D:\\a\\b\\c");
28. //创建目录:
29. //f2.mkdir();//创建单层目录
30. //f2.mkdirs();//创建多层目录
31.
32. //删除:如果是删除目录的话,只会删除一层,并且前提:这层目录是空的,里面没有内容,如果内容就不会被删除
33. f2.delete();
34.
35. //查看:
36. String[] list = f.list();//文件夹下目录/文件对应的名字的数组
37. for(String s:list){
38. System.out.println(s);
39. }
40.
41. System.out.println("=========================");
42. File[] files = f.listFiles();//作用更加广泛
43. for(File file:files){
44. System.out.println(file.getName()+","+file.getAbsolutePath());
45. }
46. }
47.}
IO流
引入
【1】File类:封装文件/目录的各种信息,对目录/文件进行操作,但是我们不可以获取到文件/目录中的内容。
【2】引入:IO流:
I/O : Input/Output的缩写,用于处理设备之间的数据的传输。
【3】形象理解:IO流 当做一根 “管”:
【4】IO流的体系结构:
案例:通过java程序完成文件的复制操作
功能分解1:文件--》程序:FileReader
一个字符一个字符的将文件中的内容读取到程序中了:
1.package com.msb.io01;
2.
3.import java.io.File;
4.import java.io.FileNotFoundException;
5.import java.io.FileReader;
6.import java.io.IOException;
7.
8./**
9. * @author : msb-zhaoss
10. */
11.public class Test01 {
12. //这是一个main方法,是程序的入口:
13. public static void main(String[] args) throws IOException {
14. //文件--》程序:
15. //1.有一个文件:----》创建一个File类的对象
16. File f = new File("d:\\Test.txt");
17. //2.利用FileReader这个流,这个“管”怼到源文件上去 ---》创建一个FileReader的流的对象
18. FileReader fr = new FileReader(f);
19. //3.进行操作“吸”的动作 ---》读取动作
20. /*下面的代码我们验证了:如果到了文件的结尾处,那么读取的内容为-1
21. int n1 = fr.read();
22. int n2 = fr.read();
23. int n3 = fr.read();
24. int n4 = fr.read();
25. int n5 = fr.read();
26. int n6 = fr.read();
27. System.out.println(n1);
28. System.out.println(n2);
29. System.out.println(n3);
30. System.out.println(n4);
31. System.out.println(n5);
32. System.out.println(n6);*/
33. //方式1:
34. /*int n = fr.read();
35. while(n!=-1){
36. System.out.println(n);
37. n = fr.read();
38. }*/
39.
40. //方式2:
41. int n;
42. while((n = fr.read())!=-1){
43. System.out.println((char)n);
44. }
45.
46. //4.“管”不用了,就要关闭 ---》关闭流
47. //流,数据库,网络资源,靠jvm本身没有办法帮我们关闭,此时必须程序员手动关闭:
48. fr.close();
49. }
50.}
想一次性读取五个字符,不够的话下次再读五个字符:
1.package com.msb.io01;
2.
3.import java.io.File;
4.import java.io.FileReader;
5.import java.io.IOException;
6.
7./**
8. * @author : msb-zhaoss
9. */
10.public class Test02 {
11. //这是一个main方法,是程序的入口:
12. public static void main(String[] args) throws IOException {
13. //文件--》程序:
14. //1.创建一个File类的对象
15. File f = new File("d:\\Test.txt");
16. //2.创建一个FileReader的流的对象
17. FileReader fr = new FileReader(f);
18. //3.读取动作
19. //引入一个“快递员的小车”,这个“小车”一次拉5个快递:
20. char[] ch = new char[5];//缓冲数组
21. int len = fr.read(ch);//一次读取五个:返回值是这个数组中 的有效长度
22. while(len!=-1){
23. //System.out.println(len);
24. //错误方式:
25. /*for (int i = 0 ;i < ch.length;i++){
26. System.out.println(ch[i]);
27. }*/
28. //正确方式:
29. /*for (int i = 0 ;i < len;i++){
30. System.out.println(ch[i]);
31. }*/
32. //正确方式2:将数组转为String:
33. String str = new String(ch,0,len);
34. System.out.print(str);
35. len = fr.read(ch);
36. }
37.
38.
39. //4.关闭流
40. fr.close();
41. }
42.}
功能分解2:程序--》文件:FileWriter
一个字符一个字符的向外输出:
1.package com.msb.io01;
2.
3.import java.io.File;
4.import java.io.FileWriter;
5.import java.io.IOException;
6.
7./**
8. * @author : msb-zhaoss
9. */
10.public class Test03 {
11. //这是一个main方法,是程序的入口:
12. public static void main(String[] args) throws IOException {
13. //1.有个目标文件:
14. File f = new File("d:\\demo.txt");
15. //2.FileWriter管怼到文件上去:
16. FileWriter fw = new FileWriter(f);
17. //3.开始动作:输出动作:
18. //一个字符一个字符的往外输出:
19. String str = "hello你好";
20. for (int i = 0 ;i < str.length();i++){
21. fw.write(str.charAt(i));
22. }
23. //4.关闭流:
24. fw.close();
25. }
26.}
发现:
如果目标文件不存在的话,那么会自动创建此文件。
如果目标文件存在的话:
new FileWriter(f) 相当于对原文件进行覆盖操作。
new FileWriter(f,false) 相当于对源文件进行覆盖操作。不是追加。
new FileWriter(f,true) 对原来的文件进行追加,而不是覆盖。
利用缓冲数组:向外输出(利用缓冲数组:)
1.package com.msb.io01;
2.
3.import java.io.File;
4.import java.io.FileWriter;
5.import java.io.IOException;
6.
7./**
8. * @author : msb-zhaoss
9. */
10.public class Test03 {
11. //这是一个main方法,是程序的入口:
12. public static void main(String[] args) throws IOException {
13. //1.有个目标文件:
14. File f = new File("d:\\demo.txt");
15. //2.FileWriter管怼到文件上去:
16. FileWriter fw = new FileWriter(f,true);
17. //3.开始动作:输出动作:
18. //一个字符一个字符的往外输出:
19. String str = "你好中国";
20. char[] chars = str.toCharArray();
21. fw.write(chars);
22. //4.关闭流:
23. fw.close();
24. }
25.}
功能分解3:利用FileReader,FileWriter文件复制
1.package com.msb.io01;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test04 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //1.有一个源文件
12. File f1 = new File("d:\\Test.txt");
13. //2.有一个目标文件:
14. File f2 = new File("d:\\Demo.txt");
15. //3.搞一个输入的管 怼到源文件上:
16. FileReader fr = new FileReader(f1);
17. //4.搞一个输出的管,怼到目标文件上:
18. FileWriter fw = new FileWriter(f2);
19.
20. //5.开始动作:
21. //方式1:一个字符一个字符的复制:
22. /*int n = fr.read();
23. while(n!=-1){
24. fw.write(n);
25. n = fr.read();
26. }*/
27.
28. //方式2:利用缓冲字符数组:
29. /*char[] ch = new char[5];
30. int len = fr.read(ch);
31. while(len!=-1){
32. fw.write(ch,0,len);//将缓冲数组中有效长度写出
33. len = fr.read(ch);
34. }*/
35. //方式3:利用缓冲字符数组,将数组转为String写出。
36. char[] ch = new char[5];
37. int len = fr.read(ch);
38. while(len!=-1){
39. String s = new String(ch,0,len);
40. fw.write(s);
41. len = fr.read(ch);
42. }
43.
44. //6.关闭流:(关闭流的时候,倒着关闭,后用先关)
45. fw.close();
46. fr.close();
47.
48.
49. }
50.}
51.
警告:不要用字符流去操作非文本文件
文本文件:.txt .java .c .cpp ---》建议使用字符流操作
非文本文件:.jpg, .mp3 , .mp4 , .doc , .ppt ---》建议使用字节流操作
利用try-catch-finally处理异常方式
1.package com.msb.io01;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test04 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) {
11. //1.有一个源文件
12. File f1 = new File("d:\\Test.txt");
13. //2.有一个目标文件:
14. File f2 = new File("d:\\Demo.txt");
15. //3.搞一个输入的管 怼到源文件上:
16. FileReader fr = null;
17. FileWriter fw = null;
18. try {
19. fr = new FileReader(f1);
20. //4.搞一个输出的管,怼到目标文件上:
21. fw = new FileWriter(f2);
22.
23. //5.开始动作:
24. char[] ch = new char[5];
25. int len = fr.read(ch);
26. while(len!=-1){
27. String s = new String(ch,0,len);
28. fw.write(s);
29. len = fr.read(ch);
30. }
31. } catch (FileNotFoundException e) {
32. e.printStackTrace();
33. } catch (IOException e) {
34. e.printStackTrace();
35. } finally {
36. //6.关闭流:(关闭流的时候,倒着关闭,后用先关)
37. try {
38. if(fw!=null){//防止空指针异常
39. fw.close();
40. }
41. } catch (IOException e) {
42. e.printStackTrace();
43. }
44.
45. try {
46. if(fr!=null){
47. fr.close();
48. }
49. } catch (IOException e) {
50. e.printStackTrace();
51. }
52.
53. }
54.
55.
56.
57.
58.
59. }
60.}
FileInputStream读取文件中内容
【1】读取文本文件:
1.package com.msb.io02;
2.
3.import java.io.File;
4.import java.io.FileInputStream;
5.import java.io.FileNotFoundException;
6.import java.io.IOException;
7.
8./**
9. * @author : msb-zhaoss
10. */
11.public class Test01 {
12. //这是一个main方法,是程序的入口:
13. public static void main(String[] args) throws IOException {
14. //功能:利用字节流将文件中内容读到程序中来:
15. //1.有一个源文件:
16. File f = new File("D:\\Test.txt");
17. //2.将一个字节流这个管 怼 到 源文件上:
18. FileInputStream fis = new FileInputStream(f);
19. //3.开始读取动作
20. /*
21. 细节1:
22. 文件是utf-8进行存储的,所以英文字符 底层实际占用1个字节
23. 但是中文字符,底层实际占用3个字节。
24.
25. 细节2:
26. 如果文件是文本文件,那么就不要使用字节流读取了,建议使用字符流。
27.
28. 细节3:
29. read()读取一个字节,但是你有没有发现返回值是 int类型,而不是byte类型?
30. read方法底层做了处理,让返回的数据都是“正数”
31. 就是为了避免如果字节返回的是-1的话,那到底是读入的字节,还是到文件结尾呢。
32. */
33. int n = fis.read();
34. while(n!=-1){
35. System.out.println(n);
36. n = fis.read();
37. }
38. //4.关闭流:
39. fis.close();
40.
41. }
42.}
43.
【2】利用字节流读取非文本文件:(以图片为案例:)--》一个字节一个字节的读取:
1.package com.msb.io02;
2.
3.import java.io.File;
4.import java.io.FileInputStream;
5.import java.io.IOException;
6.
7./**
8. * @author : msb-zhaoss
9. */
10.public class Test02 {
11. //这是一个main方法,是程序的入口:
12. public static void main(String[] args) throws IOException {
13. //功能:利用字节流将文件中内容读到程序中来:
14. //1.有一个源文件:
15. File f = new File("D:\\LOL.jpg");
16. //2.将一个字节流这个管 怼 到 源文件上:
17. FileInputStream fis = new FileInputStream(f);
18. //3.开始读取动作
19. int count = 0;//定义一个计数器,用来计读入的字节的个数
20. int n = fis.read();
21. while(n!=-1){
22. count++;
23. System.out.println(n);
24. n = fis.read();
25. }
26. System.out.println("count="+count);
27. //4.关闭流:
28. fis.close();
29.
30. }
31.}
【3】利用字节类型的缓冲数组:
1.package com.msb.io02;
2.
3.import java.io.File;
4.import java.io.FileInputStream;
5.import java.io.IOException;
6.
7./**
8. * @author : msb-zhaoss
9. */
10.public class Test03 {
11. //这是一个main方法,是程序的入口:
12. public static void main(String[] args) throws IOException {
13. //功能:利用字节流将文件中内容读到程序中来:
14. //1.有一个源文件:
15. File f = new File("D:\\LOL.jpg");
16. //2.将一个字节流这个管 怼 到 源文件上:
17. FileInputStream fis = new FileInputStream(f);
18. //3.开始读取动作
19. //利用缓冲数组:(快递员的小车)
20. byte[] b = new byte[1024*6];
21. int len = fis.read(b);//len指的就是读取的数组中的有效长度
22. while(len!=-1){
23. //System.out.println(len);
24. for(int i = 0;i<len;i++){
25. System.out.println(b[i]);
26. }
27. len = fis.read(b);
28. }
29. //4.关闭流:
30. fis.close();
31.
32. }
33.}
FileInputStream,FileOutputStream完成非文本文件的复制
【1】读入一个字节,写出一个字节:
1.package com.msb.io02;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test04 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //功能:完成图片的复制:
12. //1.有一个源图片
13. File f1 = new File("d:\\LOL.jpg");
14. //2.有一个目标图片:
15. File f2 = new File("d:\\LOL2.jpg");
16. //3.有一个输入的管道 怼 到 源文件:
17. FileInputStream fis = new FileInputStream(f1);
18. //4.有一个输出的管道 怼到 目标文件上:
19. FileOutputStream fos = new FileOutputStream(f2);
20. //5.开始复制:(边读边写)
21. int n = fis.read();
22. while(n!=-1){
23. fos.write(n);
24. n = fis.read();
25. }
26. //6.关闭流:(倒着关闭流,先用后关)
27. fos.close();
28. fis.close();
29.
30.
31. }
32.}
【2】利用缓冲字节数组:
1.package com.msb.io02;
2.
3.import java.io.File;
4.import java.io.FileInputStream;
5.import java.io.FileOutputStream;
6.import java.io.IOException;
7.
8./**
9. * @author : msb-zhaoss
10. */
11.public class Test05 {
12. //这是一个main方法,是程序的入口:
13. public static void main(String[] args) throws IOException {
14. //功能:完成图片的复制:
15. //1.有一个源图片
16. File f1 = new File("d:\\LOL.jpg");
17. //2.有一个目标图片:
18. File f2 = new File("d:\\LOL2.jpg");
19. //3.有一个输入的管道 怼 到 源文件:
20. FileInputStream fis = new FileInputStream(f1);
21. //4.有一个输出的管道 怼到 目标文件上:
22. FileOutputStream fos = new FileOutputStream(f2);
23. //5.开始复制:(边读边写)
24. //利用缓冲数组:
25. byte[] b = new byte[1024*8];
26. int len = fis.read(b);
27. while(len!=-1){
28. fos.write(b,0,len);
29. len = fis.read(b);
30. }
31. //6.关闭流:(倒着关闭流,先用后关)
32. fos.close();
33. fis.close();
34.
35.
36. }
37.}
缓冲字节流(处理流)-BufferedInputStream ,BufferedOutputStream
【1】读入一个字节,写出一个字节:
【2】利用缓冲字节数组:
【3】利用缓冲区:
想要完成上面的效果,单纯的靠FileInputStream,FileOutputStream是不可以完成的,这个时候就需要功能的加强,
这个加强就需要引入新的流(在FileInputStream,FileOutputStream外面再套一层流):BufferedInputStream ,BufferedOutputStream. ----->处理流
代码:
1.package com.msb.io02;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test06 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //1.有一个源图片
12. File f1 = new File("d:\\LOL.jpg");
13. //2.有一个目标图片:
14. File f2 = new File("d:\\LOL2.jpg");
15. //3.有一个输入的管道 怼 到 源文件:
16. FileInputStream fis = new FileInputStream(f1);
17. //4.有一个输出的管道 怼到 目标文件上:
18. FileOutputStream fos = new FileOutputStream(f2);
19. //5.功能加强,在FileInputStream外面套一个管:BufferedInputStream:
20. BufferedInputStream bis = new BufferedInputStream(fis);
21. //6.功能加强,在FileOutputStream外面套一个管:BufferedOutputStream:
22. BufferedOutputStream bos = new BufferedOutputStream(fos);
23.
24. //7.开始动作 :
25. byte[] b = new byte[1024*6];
26. int len = bis.read(b);
27. while(len!=-1){
28. bos.write(b,0,len);
29. /* bos.flush(); 底层已经帮我们做了刷新缓冲区的操作,不用我们手动完成:底层调用flushBuffer()*/
30. len = bis.read(b);
31. }
32.
33. //8.关闭流:
34. //倒着关:
35. //如果处理流包裹着节点流的话,那么其实只要关闭高级流(处理流),那么里面的字节流也会随之被关闭。
36. bos.close();
37. bis.close();
38. /*fos.close();
39. fis.close();*/
40. }
41.}
比对非文本文件复制的三种方法的效率
【1】读入一个字节,写出一个字节:
【2】利用缓冲字节数组:
【3】利用缓冲区:
代码:
1.package com.msb.io02;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test06 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //1.有一个源图片
12. File f1 = new File("d:\\LOL.jpg");
13. //2.有一个目标图片:
14. File f2 = new File("d:\\LOL2.jpg");
15. //3.有一个输入的管道 怼 到 源文件:
16. FileInputStream fis = new FileInputStream(f1);
17. //4.有一个输出的管道 怼到 目标文件上:
18. FileOutputStream fos = new FileOutputStream(f2);
19. //5.功能加强,在FileInputStream外面套一个管:BufferedInputStream:
20. BufferedInputStream bis = new BufferedInputStream(fis);
21. //6.功能加强,在FileOutputStream外面套一个管:BufferedOutputStream:
22. BufferedOutputStream bos = new BufferedOutputStream(fos);
23.
24. //7.开始动作 :
25. long startTime = System.currentTimeMillis();
26. byte[] b = new byte[1024];
27. int len = bis.read(b);
28. while(len!=-1){
29. bos.write(b,0,len);
30. /* bos.flush(); 底层已经帮我们做了刷新缓冲区的操作,不用我们手动完成:底层调用flushBuffer()*/
31. len = bis.read(b);
32. }
33. long endTime = System.currentTimeMillis();
34. System.out.println("复制完成的时间为:"+(endTime-startTime));
35. //8.关闭流:
36. //倒着关:
37. //如果处理流包裹着节点流的话,那么其实只要关闭高级流(处理流),那么里面的字节流也会随之被关闭。
38. bos.close();
39. bis.close();
40. /*fos.close();
41. fis.close();*/
42. }
43.}
缓冲字符流(处理流)-BufferedReader,BufferedWriter完成文本文件的复制
1.package com.msb.io02;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test07 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //1.有一个源文件:
12. File f1 = new File("d:\\Test.txt");
13. //2.有一个目标文件:
14. File f2 = new File("d:\\Demo.txt");
15. //3.需要一个管 怼到 源文件:
16. FileReader fr = new FileReader(f1);
17. //4.需要一根管怼到目标文件:
18. FileWriter fw = new FileWriter(f2);
19. //5.套一根管在输入字符流外面:
20. BufferedReader br = new BufferedReader(fr);
21. //6.套一根管在输出字符流外面:
22. BufferedWriter bw = new BufferedWriter(fw);
23. //7.开始动作:
24. //方式1:读取一个字符,输出一个字符:
25. /*int n = br.read();
26. while(n!=-1){
27. bw.write(n);
28. n = br.read();
29. }*/
30.
31. //方式2:利用缓冲数组:
32. /*char[] ch = new char[30];
33. int len = br.read(ch);
34. while(len!=-1){
35. bw.write(ch,0,len);
36. len = br.read(ch);
37. }*/
38.
39. //方式3:读取String:
40. String str = br.readLine();//每次读取文本文件中一行,返回字符串
41. while(str!=null){
42. bw.write(str);
43. //在文本文件中应该再写出一个换行:
44. bw.newLine();//新起一行
45. str = br.readLine();
46. }
47.
48.
49. //8.关闭流
50. bw.close();
51. br.close();
52. }
53.}
54.
转换流-InputStreamReader,OutputStreamWriter
【1】转换流:作用:将字节流和字符流进行转换。
【2】转换流 属于 字节流还是字符流?属于字符流
InputStreamReader :字节输入流 ---》字符的输入流
OutputStreamWriter : 字符输出流 --》字节的输出流
【3】图解:
【4】将输入的字节流转换为输入的字符流,然后完成文件--》程序 :
1.package com.msb.io03;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test01 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //文件---》程序:
12. //1.有一个源文件:
13. File f = new File("d:\\Test.txt");
14. //2.需要一个输入的字节流接触文件:
15. FileInputStream fis = new FileInputStream(f);
16. //3.加入一个转换流,将字节流转换为字符流:(转换流属于一个处理流)
17. //将字节转换为字符的时候,需要指定一个编码,这个编码跟文件本身的编码格式统一
18. //如果编码格式不统一的话,那么在控制台上展示的效果就会出现乱码
19. //InputStreamReader isr = new InputStreamReader(fis,"utf-8");
20. //获取程序本身的编码--》utf-8
21. InputStreamReader isr = new InputStreamReader(fis);
22. //4.开始动作,将文件中内容显示在控制台:
23. char[] ch = new char[20];
24. int len = isr.read(ch);
25. while(len!=-1){
26. //将缓冲数组转为字符串在控制台上打印出来
27. System.out.print(new String(ch,0,len));
28. len = isr.read(ch);
29. }
30.
31. //5.关闭流:
32. isr.close();
33. }
34.}
转换流-InputStreamReader,OutputStreamWriter实现文本文件的复制
1.package com.msb.io03;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test02 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //1.有一个源文件
12. File f1 = new File("d:\\Test.txt");
13. //2.有一个目标文件:
14. File f2 = new File("d:\\Demo.txt");
15. //3.输入方向:
16. FileInputStream fis = new FileInputStream(f1);
17. InputStreamReader isr = new InputStreamReader(fis,"utf-8");
18. //4.输出方向:
19. FileOutputStream fos = new FileOutputStream(f2);
20. OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
21. //5.开始动作:
22. char[] ch = new char[20];
23. int len = isr.read(ch);
24. while(len!=-1){
25. osw.write(ch,0,len);
26. len = isr.read(ch);
27. }
28.
29. //6.关闭流:
30. osw.close();
31. isr.close();
32.
33. }
34.}
System类对IO流的支持
【1】System的属性:
System.in : “标准”输入流。---》默认情况下 从键盘输入
System.out :“标准”输出流。 ---》默认情况下,输出到控制台。
【2】System.in :“标准”输入流。---》默认情况下 从键盘输入
1.public class Test01 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) throws IOException {
4. //得到的是标准的输入流:--》从键盘输入:
5. //InputStream in = System.in;
6. //调用方法:
7. //int n = in.read();//read方法等待键盘的录入,所以这个方法是一个阻塞方法。
8. //System.out.println(n);
9.
10. //以前案例:从键盘录入一个int类型的数据:
11. //从上面的代码证明,键盘录入实际上是:System.in
12. //形象的理解:System.in管,这个管怼到键盘上去了,所以你从键盘录入的话,就从这个管到程序中了
13. //Scanner的作用:扫描器:起扫描作用的,扫键盘的从这根管出来的数据
14. /*Scanner sc = new Scanner(System.in);
15. int i = sc.nextInt();
16. System.out.println(i);*/
17.
18. //既然Scanner是扫描的作用,不一定非得扫 System.in进来的东西,还可以扫描其他管的内容:
19. Scanner sc = new Scanner(new FileInputStream(new File("d:\\Test.txt")));
20. while(sc.hasNext()){
21. System.out.println(sc.next());
22. }
23.
24. }
25.}
【3】System.out : 返回的输出流 、 打印流(PrintStream)
1.package com.msb.io04;
2.
3.import java.io.PrintStream;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test02 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) {
11. //写到控制台:
12. PrintStream out = System.out;
13. //调用方法:
14. out.print("你好1");//直接在控制台写出,但是不换行
15. out.print("你好2");
16. out.print("你好3");
17. out.print("你好4");
18.
19. out.println("我是中国人1");//直接在控制台写出,并且换行操作
20. out.println("我是中国人2");
21. out.println("我是中国人3");
22. out.println("我是中国人4");
23.
24. System.out.println("你是");
25. System.out.print("中国人");
26.
27. }
28.}
练习:键盘录入内容输出到文件中
【1】解决思路:
【2】代码:
1.package com.msb.io04;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test03 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //1.先准备输入方向:
12. //键盘录入:
13. InputStream in = System.in;//属于字节流
14. //字节流--》字符流:
15. InputStreamReader isr = new InputStreamReader(in);
16. //在isr外面再套一个缓冲流:
17. BufferedReader br = new BufferedReader(isr);
18.
19. //2.再准备输出方向:
20. //准备目标文件
21. File f = new File("d:\\Demo1.txt");
22. FileWriter fw = new FileWriter(f);
23. BufferedWriter bw = new BufferedWriter(fw);
24.
25. //3.开始动作:
26. String s = br.readLine();
27. while(!s.equals("exit")){
28. bw.write(s);
29. bw.newLine();//文件中换行
30. s = br.readLine();
31. }
32.
33. //4.关闭流:
34. bw.close();
35. br.close();
36. }
37.}
数据流-DataInputStream,DataOutputStream
【1】数据流:用来操作基本数据类型和字符串的
【2】
DataInputStream:将文件中存储的基本数据类型和字符串 写入 内存的变量中
DataOutputStream: 将内存中的基本数据类型和字符串的变量 写出 文件中
【3】代码:
利用DataOutputStream向外写出变量:
1.public class Test01 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) throws IOException {
4. //DataOutputStream: 将内存中的基本数据类型和字符串的变量 写出 文件中
5. /*File f = new File("d:\\Demo2.txt");
6. FileOutputStream fos = new FileOutputStream(f);
7. DataOutputStream dos = new DataOutputStream(fos);*/
8. DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("d:\\Demo2.txt")));
9. //向外将变量写到文件中去:
10. dos.writeUTF("你好");
11. dos.writeBoolean(false);
12. dos.writeDouble(6.9);
13. dos.writeInt(82);
14.
15. //关闭流:
16. dos.close();
17. }
18.}
在Demo2.txt文件中,我们看到:
发现:这个内容我们看不懂,是给程序看的
所以下面我们开始读取的程序:
1.package com.msb.io05;
2.
3.import java.io.*;
4.
5./**
6. * @author : msb-zhaoss
7. */
8.public class Test02 {
9. //这是一个main方法,是程序的入口:
10. public static void main(String[] args) throws IOException {
11. //DataInputStream:将文件中存储的基本数据类型和字符串 写入 内存的变量中
12. DataInputStream dis = new DataInputStream(new FileInputStream(new File("d:\\Demo2.txt")));
13. //将文件中内容读取到程序中来:
14. System.out.println(dis.readUTF());
15. System.out.println(dis.readBoolean());
16. System.out.println(dis.readDouble());
17. System.out.println(dis.readInt());
18.
19. //关闭流:
20. dis.close();
21.
22. }
23.}
结果:
验证:那个文件,我们看不懂,程序看得懂
要求:
写出的类型跟读入的类型 必须 要匹配!
对象流-ObjectInputStream,ObjectOutputStream
【1】对象流:ObjectInputStream,ObjectInputStream
用于存储和读取基本数据类型数据或对象的处理流。
它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
【2】序列化和反序列化:
ObjectOutputStream 类 : 把内存中的Java对象转换成平台无关的二进制数据,从而允许把这种二进制数据持久地保存在磁盘上,或通过网络将这种二进制数据传输到另一个网络节点。----》序列化
用ObjectInputStream类 : 当其它程序获取了这种二进制数据,就可以恢复成原来的Java对象。----》反序列化
【3】代码:操作字符串对象:
首先将一个字符串对象写到文件中去:----》序列化
1.public class Test01 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) throws IOException {
4.
5. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:\\Demo3.txt")));
6. //将内存中的字符串写出到文件中:
7. oos.writeObject("你好");
8. //关闭流:
9. oos.close();
10. }
11.}
查看文件:
我们看不懂文件的内容,但是程序是可以看懂的,所以可以写一个程序读文件中内容:----》反序列化
1.public class Test02 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) throws IOException, ClassNotFoundException {
4. //将文件中保存的字符串 读入到 内存:
5. ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:\\Demo3.txt")));
6. //读取:
7. String s = (String)(ois.readObject());
8. System.out.println(s);
9. //关闭流:
10. ois.close();
11. }
12.}
控制台:
【4】代码:操作自定义类的对象:
自定义的Person类:
1.public class Person {
2. private String name;
3. private int age;
4.
5. public String getName() {
6. return name;
7. }
8.
9. public void setName(String name) {
10. this.name = name;
11. }
12.
13. public int getAge() {
14. return age;
15. }
16.
17. public void setAge(int age) {
18. this.age = age;
19. }
20.
21. public Person() {
22. }
23.
24. public Person(String name, int age) {
25. this.name = name;
26. this.age = age;
27. }
28.}
测试类:
1.public class Test01 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) throws IOException {
4. //序列化:将内存中对象 ---》 文件:
5. //有一个对象:
6. Person p = new Person("lili",19);
7. //有对象流:
8. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:\\Demo4.txt")));
9. //向外写:
10. oos.writeObject(p);
11. //关闭流:
12. oos.close();
13. }
14.}
运行的时候发现出现异常:
出现异常的原因:
你想要序列化的那个对象对应的类,必须要实现一个接口:
接口内部,什么都没有,这种接口叫 标识接口。
起到标识作用,标识什么呢?只要实现这个接口的类的对象才能序列化,否则不可以。
解决办法:将Person 实现这个标识接口就可以:
1.public class Person implements Serializable {
2. private String name;
3. private int age;
4.
5. public String getName() {
6. return name;
7. }
8.
9. public void setName(String name) {
10. this.name = name;
11. }
12.
13. public int getAge() {
14. return age;
15. }
16.
17. public void setAge(int age) {
18. this.age = age;
19. }
20.
21. public Person() {
22. }
23.
24. public Person(String name, int age) {
25. this.name = name;
26. this.age = age;
27. }
28.}
测试:发现序列化成功,Person具备了序列化的能力。
这个二进制数据我们看不懂,但是程序可以看懂,所以我们可以用程序实现 反序列化操作:
将这个对象 恢复到内存中来:
1.public class Test02 {
2. //这是一个main方法,是程序的入口:
3. public static void main(String[] args) throws IOException, ClassNotFoundException {
4. ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:\\Demo4.txt")));
5. //读入内存:
6. Person p = (Person)(ois.readObject());
7. System.out.println(p/*.toString()*/);
8. //关闭流:
9. ois.close();
10. }
11.}
结果:
因为我们没有重写toString方法,所以结果为
证明了反序列化成功: 将二进制数据 --》内存
【5】serialVersionUID:
凡是实现Serializable接口(标识接口)的类都有一个表示序列化版本标识符的静态常量:
➢private static final long serialVersionUID;
➢serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序加化时是否兼容。
➢如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,显式声明。
➢简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
我现在在Person类中加入toString方法:
1.public class Person implements Serializable {
2. private String name;
3. private int age;
4.
5. public String getName() {
6. return name;
7. }
8.
9. public void setName(String name) {
10. this.name = name;
11. }
12.
13. public int getAge() {
14. return age;
15. }
16.
17. public void setAge(int age) {
18. this.age = age;
19. }
20.
21. public Person() {
22. }
23.
24. public Person(String name, int age) {
25. this.name = name;
26. this.age = age;
27. }
28.
29. @Override
30. public String toString() {
31. return "Person{" +
32. "name='" + name + '\'' +
33. ", age=" + age +
34. '}';
35. }
36.}
再次运行测试类:
出现异常:
出现异常的原因:
解决:给这个类 加入一个 序列号:serialVersionUID
【6】IDEA中配置序列化版本号:
在Person类上:alt+enter:
回车即可生成
【7】序列化细节:
(1)被序列化的类的内部的所有属性,必须是可序列化的 (基本数据类型都是可序列化的)
static,transient修饰的属性 不可以被序列化。
1.public class Person implements Serializable {
2.
3. private static final long serialVersionUID = 8027651838638826533L;
4. private transient String name;
5. private static int age;
6. private Famaily f = new Famaily();
7.
8. public String getName() {
9. return name;
10. }
11.
12. public void setName(String name) {
13. this.name = name;
14. }
15.
16. public int getAge() {
17. return age;
18. }
19.
20. public void setAge(int age) {
21. this.age = age;
22. }
23.
24. public Person() {
25. }
26.
27. @Override
28. public String toString() {
29. return "Person{" +
30. "name='" + name + '\'' +
31. ", f=" + f + ",age=" + age +
32. '}';
33. }
34.}
结果: