十四、IO

一、概述:

1.流的分类:

  按照流向的不同分为:输入流 输出流
  按照处理数据单位的不通分为:字节流 字符流(处理的文本文件)
  按照角色的不通分为 节点流(直接作用于文件的)处理流

关于处理流的说明:(处理流作用在节点流上)

 2.IO的体系:

  抽象基类 节点流(文件流) 缓冲流
InputStream(字节流) FileInputStream BufferedInputStream
OutputStream(字节流) FileOutputStream BufferedOutputStream
  Reader(字符流) FileReader BufferedReader
  Writer(字符流) FileWriter BufferedWriter

 

 

 

 

 

 

 3.如何使用

  •   对于文本文件(.txt,.java,.c,.cpp)使用字符流处理
  •   对于非文本文件,使用字节流处理

二、节点流

1、FileReaderd

1.1步骤:

  • 创建File类对象,指明要操作的文件;
  • 提供具体的流
  • 数据的处理
  • 关闭应用的流

demo1:从硬盘存在的一个文件中,读取其内容到程序中,使用FileInputStream,显示在控制台上

 1 @Test
 2 
 3     public void testStream1() {
 4 
 5         // 2.提供具体的流
 6         FileReader fileReader = null;
 7         try {
 8 
 9             // 1.创建一个File类的对象,指明要操作的文件
10 
11             File file1 = new File("hello.txt");// 文件位置为当前工程下面,不是当前类下
12             fileReader = new FileReader(file1);
13             // 3.数据的读入
14             // read() 返回读入的一个字符,文件达到末尾,则返回-1
15             int data = fileReader.read();
16             while (data != -1) {
17                 System.out.print((char) data);
18                 data = fileReader.read();
19             }
20         } catch (FileNotFoundException e) {
21             // TODO Auto-generated catch block
22             e.printStackTrace();
23         } catch (IOException e) {
24             // TODO Auto-generated catch block
25             e.printStackTrace();
26         } finally {
27             // 4.关闭相应的流
28             if (fileReader != null) {
29                 try {
30                     fileReader.close();
31                 } catch (IOException e) {
32                     e.printStackTrace();
33                 }
34             }
35 
36         }
37 
38     }

注意:要读取的文件一定要存在,否则空指针异常

说明:

  • read()的理解:返回读入的一直字符,如果到底文件末尾则返回-1;
  • 关于异常的处理,为了保证保证流资源的关闭,这里使用了try catch finally 来处理,这里看到了顺序没有从上到下来,是因为最后做了异常处理导致的;

1.2.关于read方法的详细说明

1.2.1read()方法错误版(只为说明用)

 1 /
 2       reader 方法升级版(错误版)
 3  4       @Description
 5 @author lixiuming
 6       @date 2021年5月5日上午11:22:37
 7 @throws IOException
 8  9      /
10     @Test
11     public void testReaderUpgrade2() throws IOException {
12         // 1.File 类的实例化
13         File file1 = new File("hello.txt");// 文件位置为当前工程下面,不是当前类下
14         // 2.流的实例化
15         FileReader fileReader = new FileReader(file1);
16         // 3.流的写出
17         char[] charArr = new char[5];// 一次读入多个数据来提高效率
18         int len = fileReader.read(charArr);// 一次读入多个数据,返回每次读入的charArr数组中字符的个数,如果达到文件末尾,返回-1
19         while (len != -1) {
20             for (int i = 0; i < charArr.length; i++) {
21                 System.out.print((char) charArr[i]);
22             }
23             len = fileReader.read(charArr);
24         }
25         // 4.流的操作
26         fileReader.close();
27 
28     }

这里的charArr.length;有问题,在文件中,如果hello.txt中的内容是:hello word!! hello lixiuming!!123,那么此时的输出结果就是 hello word!! hello lixiuming!!123!!,多了两个“!!”;

若最后取的数组长度不足5,那么前一个的数组是:

i n g

 

 

最后一组数组则是:

1 3 2

 

 

没有覆盖掉原来的数据;

1.2.2read()的升级版本正确写法:

 1 /
 2       reader 方法的升级版(正确版)
 3  4       @Description
 5 @author lixiuming
 6 @throws IOException
 7       @date 2021年5月5日上午10:55:53
 8  9      /
10     @Test
11     public void testReaderUpgrade() throws IOException {
12         // 1.File 类的实例化
13         File file1 = new File("hello.txt");// 文件位置为当前工程下面,不是当前类下
14         // 2.流的实例化
15         FileReader fileReader = new FileReader(file1);
16         // 3.流的写出
17         char[] charArr = new char[5];// 一次读入多个数据来提高效率
18         int len = fileReader.read(charArr);// 一次读入多个数据,返回每次读入的charArr数组中字符的个数,如果达到文件末尾,返回-1
19         while (len != -1) {
20             for (int i = 0; i < len; i++) {
21                 System.out.print((char) charArr[i]);
22 
23             }
24             len = fileReader.read(charArr);
25         }
26         // 4.流的操作
27         fileReader.close();
28 
29     }

2.FileWrite

步骤:

  • 创建File类对象,指明要操作的文件;
  • 提供具体的流
  • 数据的处理
  • 关闭应用的流

demo:从内存中写出数据到硬盘的文件里的简单说明

 1 @Test
 2     public void testFileWirter() throws IOException {
 3         // 1、提供File类的对象,指明写出到的文件
 4         File file = new File("hello2.txt");
 5         // 2.提供FileWrite的对象,用于数据的写出
 6         FileWriter fw = new FileWriter(file);
 7         // 3.写出的具体操作
 8 
 9         fw.write("I have a dream!");
10         fw.write("You need have a dream!");
11         // 4.关闭流
12         fw.close();
13 
14     }
View Code

说明:

输出操作,对应File可以不存在,并不会报异常;

如不存在,在输出过程中自动穿件文件

如果存在, a.如果流构造器使用的是FileWriter(file,false)/FileWriter(file),对象会对原有的文件进行覆盖;

      b.如果流构造器使用的是FileWriter(file,true) 不会对原有的文件覆盖,而是在原有的文件内追加;

 

3.文件的复制(FileReader和FileWriter同时使用)

3.1JUNIT测试版:

 1 /
 2       文件的复制
 3  4       @Description
 5 @author lixiuming
 6 @throws IOException
 7       @date 2021年5月5日上午10:19:44
 8  9      /
10     @Test
11     public void testFileCopy() {
12         // 2.创建输入和出入流的对象
13         FileReader fr = null;
14         FileWriter fw = null;
15         try {
16             // 1.创建File 类的对象,指明读入和写出的文件
17             File copy = new File("hello.txt");
18             File copyTo = new File("hello2.txt");
19             fr = new FileReader(copy);
20             fw = new FileWriter(copyTo);
21             // 3.数据的读入和写出
22             char[] charArr = new char[5];
23             int len = fr.read(charArr);
24             while (len != -1) {
25                 for (int i = 0; i < len; i++) {
26                     char data = (char) charArr[i];
27                     fw.write(data);
28                 }
29                 len = fr.read(charArr);
30             }
31         } catch (Exception e) {
32         } finally {
33             // 4.关闭流资源
34             try {
35                 if (fw != null) {
36                     fw.close();
37                 }
38 
39             } catch (IOException e) {
40                 e.printStackTrace();
41             } finally {
42                 if (fr != null) {
43                     try {
44                         fr.close();
45                     } catch (IOException e) {
46                         e.printStackTrace();
47                     }
48                 }
49             }
50 
51         }
52 
53     }

4、FileInputStream/FileOutputStream

*4.1步骤:

  • 创建File类对象,指明要操作的文件;
  • 提供具体的流
  • 数据的处理
  • 关闭应用的流

说明:用字节流 读取文本文件(中文 数字 英文):控制台中文会有乱码,如果单纯的复制文件没有问题;

使用demo:用字节流读取文本文件

 1 @Test
 2     public void testFileInputString() {
 3         // 2.造流
 4         FileInputStream fo = null;
 5         try {
 6             // 1.造文件
 7             File file = new File("hello.txt");
 8             fo = new FileInputStream(file);
 9             // 3.文件读出
10             byte[] arr = new byte[5];
11             int len = fo.read(arr);
12             while (len != -1) {
13                 System.out.print(new String(arr, 0, len));
14                 len = fo.read(arr);
15             }
16         } catch (Exception e) {
17             // TODO: handle exception
18         } finally {
19             // 4、流关闭
20             try {
21                 if (fo != null)
22                     fo.close();
23             } catch (IOException e) {
24                 // TODO Auto-generated catch block
25                 e.printStackTrace();
26             }
27         }
28 
29     }

4.2实现图片的复制

 1 @Test
 2     public void testCopyImg() {
 3         // 2.造流
 4         FileInputStream fi = null;
 5         FileOutputStream fo = null;
 6         try {
 7             // 1.造文件
 8             File copyFile = new File("WX20210407-100610.png");
 9             File copytoFile = new File("collection.png");
10             fi = new FileInputStream(copyFile);
11             fo = new FileOutputStream(copytoFile);
12             // 3.文件读出
13             byte[] arr = new byte[5];
14             int len = fi.read(arr);
15             while (len != -1) {
16                 for (int i = 0; i < len; i++) {
17                     fo.write(arr[i]);
18                 }
19                 len = fi.read(arr);
20 
21             }
22         } catch (Exception e) {
23             // TODO: handle exception
24         } finally {
25             // 4、流关闭
26             try {
27                 if (fo != null)
28                     fo.close();
29             } catch (IOException e) {
30                 // TODO Auto-generated catch block
31                 e.printStackTrace();
32             }
33             try {
34                 if (fi != null)
35                     fi.close();
36             } catch (IOException e) {
37                 // TODO Auto-generated catch block
38                 e.printStackTrace();
39             }
40         }
41 
42     }
View Code

*4.3对文件复制的通用方法:

说明:不能使用字符流复制照片,但是 字节流可以复制文本文件,但是,如果在复制的过程中,想在控制台查看文件,可能会有中文乱码;

 1 /
 2       复制文件通用方法
 3  4       @Description
 5 @author lixiuming
 6       @date 2021年5月5日下午2:34:36
 7 @param srcStr  复制文件地址(文件名)
 8 @param destStr 复制到文件的地址(文件名)
 9 10      /
11     public void testCopFile(String srcStr, String destStr) {
12         // 2.造流
13         FileInputStream fi = null;
14         FileOutputStream fo = null;
15         try {
16             // 1.造文件
17             File copyFile = new File(srcStr);
18             File copytoFile = new File(destStr);
19             fi = new FileInputStream(copyFile);
20             fo = new FileOutputStream(copytoFile);
21             // 3.文件读出
22             byte[] arr = new byte[1024];// 一般使用1024
23             int len = fi.read(arr);
24             while (len != -1) {
25                 for (int i = 0; i < len; i++) {
26                     fo.write(arr[i]);
27                 }
28                 len = fi.read(arr);
29 
30             }
31         } catch (Exception e) {
32             // TODO: handle exception
33         } finally {
34             // 4、流关闭
35             try {
36                 if (fo != null)
37                     fo.close();
38             } catch (IOException e) {
39                 // TODO Auto-generated catch block
40                 e.printStackTrace();
41             }
42             try {
43                 if (fi != null)
44                     fi.close();
45             } catch (IOException e) {
46                 // TODO Auto-generated catch block
47                 e.printStackTrace();
48             }
49         }
50 
51     }

*三、缓冲流

1.1缓冲流的作用:可以提供效率

*1.2使用和步骤

  • 创建File类对象,指明要操作的文件;
  • 提供具体的流:节点流和缓冲流;
  • 数据的处理
  • 关闭应用的流

demo:使用缓冲流实现文件的复制:(BufferedInputStream/BufferedOutputStream)

 1 /
 2       缓冲流实现的文件复制
 3  4       @Description
 5 @author lixiuming
 6       @date 2021年5月5日下午2:58:38
 7  8      /
 9     @Test
10     public void testCopyFileByBuffer() {
11         BufferedInputStream bi = null;
12         BufferedOutputStream bo = null;
13         // 3.复制
14         byte[] arr;
15         int len;
16         try {
17             // 1.造文件
18             File copy = new File("hello.txt");
19             File copyTo = new File("hello3.txt");
20             // 2.造流
21             FileInputStream fi = new FileInputStream(copy);
22             FileOutputStream fo = new FileOutputStream(copyTo);
23             bi = new BufferedInputStream(fi);
24             bo = new BufferedOutputStream(fo);
25             arr = new byte[1024];
26             len = bi.read(arr);
27             while (len != -1) {
28                 for (int i = 0; i < len; i++) {
29                     bo.write(arr[i]);
30                 }
31                 len = bi.read(arr);
32             }
33         } catch (Exception e) {
34         } finally {
35             // 4.关闭资源
36             try {
37                 if (bo != null) {
38                     bo.close();
39                 }
40             } catch (IOException e) {
41                 e.printStackTrace();
42             }
43             try {
44                 if (bi != null) {
45                     bi.close();
46                 }
47             } catch (IOException e) {
48                 e.printStackTrace();
49             }
50         }
51 
52     }

说明,这里的造流除了 节点流还有缓冲流,因为缓冲流作用在节点流之上;

*1.3 缓冲流复制文件的通用方法

 1 public void testCopyFileByBuffer(String srcStr, String destStr) {
 2         BufferedInputStream bi = null;
 3         BufferedOutputStream bo = null;
 4         // 3.复制
 5         byte[] arr;
 6         int len;
 7         try {
 8             // 1.造文件
 9             File copy = new File(srcStr);
10             File copyTo = new File(destStr);
11             // 2.造流
12             // 2.1造节点流
13             FileInputStream fi = new FileInputStream(copy);
14             FileOutputStream fo = new FileOutputStream(copyTo);
15             // 2.2造缓冲流
16             bi = new BufferedInputStream(fi);
17             bo = new BufferedOutputStream(fo);
18             arr = new byte[1024];
19             len = bi.read(arr);
20             while (len != -1) {
21                 for (int i = 0; i < len; i++) {
22                     bo.write(arr[i]);
23                 }
24                 len = bi.read(arr);
25             }
26         } catch (Exception e) {
27         } finally {
28             // 4.关闭资源
29             // 说明,关闭外层流,内层流自动关闭;所以 file的节点流在此处自动关闭
30             try {
31                 if (bo != null) {
32                     bo.close();
33                 }
34             } catch (IOException e) {
35                 e.printStackTrace();
36             }
37             try {
38                 if (bi != null) {
39                     bi.close();
40                 }
41             } catch (IOException e) {
42                 e.printStackTrace();
43             }
44         }
45 
46     }

1.4BufferReader BufferedWriter 实现文本文件的复制

junit测试版

 1 /**
 2      * BufferReader BufferedWriter 实现文本文件的复制
 3      *
 4      * @Description
 5      * @author lixiuming
 6      * @throws IOException
 7      * @date 2021年5月5日下午3:12:32
 8      *
 9      */
10     @Test
11     public void testBufferReaderWriter() {
12         BufferedReader bi = null;
13         BufferedWriter bo = null;
14         try {
15             // 1造文件
16             File file = new File("hello.txt");
17             File copyto = new File("hello4.txt");
18             // 2.造流
19             FileReader fi = new FileReader(file);
20             FileWriter fo = new FileWriter(copyto);
21             bi = new BufferedReader(fi);
22             bo = new BufferedWriter(fo);
23             // 3.复制的处理过程
24             char[] arr = new char[1024];
25             int len = bi.read(arr);
26             while (len != -1) {
27                 for (int i = 0; i < len; i++) {
28                     bo.write(arr[i]);
29                 }
30                 len = bi.read(arr);
31             }
32         } catch (Exception e) {
33             // TODO: handle exception
34         } finally {
35             // 4.关闭流
36             try {
37                 if (bi != null) {
38                     bi.close();
39                 }
40             } catch (IOException e) {
41                 // TODO Auto-generated catch block
42                 e.printStackTrace();
43             }
44             try {
45                 if (bo != null) {
46                     bo.close();
47                 }
48             } catch (IOException e) {
49                 e.printStackTrace();
50             }
51         }
52     }
View Code

封装版:

 1 /**
 2      * BufferReader BufferedWriter 实现文本文件的复制
 3      *
 4      * @Description
 5      * @author lixiuming
 6      * @throws IOException
 7      * @date 2021年5月5日下午3:12:32
 8      *
 9      */
10     public void testBufferReaderWriterCopy(String srcStr, String destStr) {
11         BufferedReader bi = null;
12         BufferedWriter bo = null;
13         try {
14             // 1造文件
15             File file = new File(srcStr);
16             File copyto = new File(destStr);
17             // 2.造流
18             FileReader fi = new FileReader(file);
19             FileWriter fo = new FileWriter(copyto);
20             bi = new BufferedReader(fi);
21             bo = new BufferedWriter(fo);
22             // 3.复制的处理过程
23             char[] arr = new char[1024];
24             int len = bi.read(arr);
25             while (len != -1) {
26                 for (int i = 0; i < len; i++) {
27                     bo.write(arr[i]);
28                 }
29                 len = bi.read(arr);
30             }
31         } catch (Exception e) {
32             // TODO: handle exception
33         } finally {
34             // 4.关闭流
35             try {
36                 if (bi != null) {
37                     bi.close();
38                 }
39             } catch (IOException e) {
40                 // TODO Auto-generated catch block
41                 e.printStackTrace();
42             }
43             try {
44                 if (bo != null) {
45                     bo.close();
46                 }
47             } catch (IOException e) {
48                 e.printStackTrace();
49             }
50         }
51     }
View Code

四、其他流

1.转换流(属于字符流 ):

  •  InputStreamReader:将字节的输入流 转 字符的输入流;
  • OutputStreamWriter; 将字符的输出流,转字节的输出流

作用:提供字节流和字符流的转换;

通途:可以编码 和 解码;

demo:使用utf-8读取文件,使用gbk写文件;

 1 @Test
 2     public void testReaderWriter() {
 3         InputStreamReader isr = null;
 4         OutputStreamWriter osw = null;
 5         try {
 6             //1.造文件
 7             File strFile = new File("hello.txt");
 8             File destFile = new File("hello_gbk.txt");
 9             //2.造流
10             FileInputStream fi = new FileInputStream(strFile);
11             FileOutputStream fo = new FileOutputStream(destFile);
12             isr = new InputStreamReader(fi, "utf-8");
13             osw = new OutputStreamWriter(fo, "gbk");
14             //3.处理
15             char[] arr = new char[1024];
16             int len = isr.read(arr);
17             while (len != -1) {
18                 for (int i = 0; i < len; i++) {
19                     osw.write(arr[i]);
20                 }
21                 len = isr.read(arr);
22             } 
23         } catch (Exception e) {
24             // TODO: handle exception
25         }finally {
26             //4.关闭流
27             try {
28                 if(isr!=null) {
29                     isr.close();
30                 }
31             } catch (IOException e) {
32                 // TODO Auto-generated catch block
33                 e.printStackTrace();
34             }
35             try {
36                 if(osw!=null) {
37                     osw.close();
38                 }
39             } catch (IOException e) {
40                 // TODO Auto-generated catch block
41                 e.printStackTrace();
42             }
43         }
44         
45     }

2.数据流:处理基本数据类型和String数据;

DataInputStream / DataOutputStream
用于读取或写出基本数据类型的变量或者字符串
      readBoolean()
      readChar()
      readLone()
      String readUTF()
      readByte()
      readFloat()
      readShort()
      readInt()
      void readFully(byte[] b)

demo1:将基本类型数据写出到文件

 1 @Test
 2        public void testData(){
 3            FileOutputStream fos=null;
 4            DataOutputStream dos = null;
 5            try {
 6             fos = new FileOutputStream("data.txt");
 7             dos = new DataOutputStream(fos);
 8             dos.writeUTF("ksdflskdfhslkdf");
 9             dos.writeBoolean(true);
10             dos.writeLong(123123);
11         } catch (Exception e) {
12             // TODO: handle exception
13         }finally {
14             try {
15                 if(dos!=null) {
16                 dos.close();
17                 }
18             } catch (IOException e) {
19                 // TODO Auto-generated catch block
20                 e.printStackTrace();
21             }
22         }
23 
24            }
View Code

demo2:将文件 读入到内存

 1 //将基本类型和字符串从文件中读入到内存中,读入的顺序需要和写入时的顺序一致
 2       @Test
 3        public void testReadData(){
 4           DataInputStream dos = null;
 5           try {
 6             File file = new File("data.txt");
 7             FileInputStream fos = new FileInputStream(file);
 8              dos = new DataInputStream(fos);
 9             byte[] arr = new byte[1024];
10             String str = dos.readUTF();
11             Boolean bo = dos.readBoolean();
12             long lo =dos.readLong();
13             System.out.println(str+"||"+bo+"||"+bo);
14         } catch (Exception e) {
15             // TODO: handle exception
16         }finally {
17             try {
18                 if(dos!=null) {
19                     dos.close();
20                 }
21             } catch (IOException e) {
22                 // TODO Auto-generated catch block
23                 e.printStackTrace();
24             }
25         }
26            }
View Code

注意:读入内存过程中,读入的顺序需要和写入时的顺序一致

3.打印流:

字节流:PrintStream

字符流:printWriter
提供了一系列重载的print() 和println()
  改变输出位置

 

 1 @Test
 2 
 3       public void printSrtreamWriter()  {
 4       // 设置打印位置
 5       PrintStream ps = null;
 6       try {
 7         File file = new File("hello.txt");
 8         FileOutputStream fos = new FileOutputStream(file);
 9         ps = new PrintStream(fos, true);
10         System.setOut(ps);
11         for (int i = 0; i < 255; i++) {
12             System.out.print((char) i);
13             if (i % 50 == 0) {
14                 System.out.println();// 换行
15             }
16         }
17     } catch (Exception e) {
18         // TODO: handle exception
19     } finally {
20         if (ps != null) {
21             ps.close();
22         }
23     }
24 }
View Code

 

4. 标准的输入,输出流

  • System.in 标准的输入流,默认键盘输入
  • System.out 标准的输出流,默认从控制台输出
  • System.setIn()/System.setOut()可以冲洗指定输入和输出;

demo:把输入内容转化成大写,输出,当直接输入“e”或者“exit”时,退出程序

 1 @Test
 2       public void testSystemIn() {
 3       InputStream is = null;
 4 
 5       InputStreamReader isr = null;
 6       BufferedReader br = null;
 7 
 8       try {
 9         is = System.in;
10         isr = new InputStreamReader(is);
11         br = new BufferedReader(isr);
12         String str = null;
13         while (true) {
14 
15             System.out.print("请输入字符串:");
16 
17             str = br.readLine();
18 
19             if (str.equalsIgnoreCase("e") || str.equalsIgnoreCase("exit")) {
20 
21                 break;
22 
23             } else {
24 
25                 String str1 = str.toUpperCase();
26 
27                 System.out.println(str1);
28 
29             }
30 
31         }
32     } catch (Exception e) {
33         // TODO: handle exception
34     }finally {
35         if(br!=null)
36             try {
37                 br.close();
38             } catch (IOException e) {
39                 // TODO Auto-generated catch block
40                 e.printStackTrace();
41             }
42     }
43 
44       }
View Code

 

5.对象流

①作用:用于存储和读取基本数据类型数据或者对象的处理流;

    序列化:用ObjectOutputStream 类保存基本类型数据或对象的机制,应用场景:对象持久化到文件or网络传输;
    反序列化:用ObjectInputStream 类读取基本类型数据或对象,应用场景:解析对象到内存中;

②对象的序列化机制:允许把内存中的Java对象转换成与平台无关的二进制流,从而允许把这种二进制流持久的保存到磁盘上,
         或者通过网络将这种二进制流传输到另一个网络节点,当其他程序获取了这种二进制流,就可以恢复成原来的java对象;
 
③序列化的好处:可以将任意实现了Serializable接口的对象转换为字节数据,使其在保存和传输时可被还原;
 
       序列化是RMI过程的传输和返回值都必须实现的机制,而RMI是java EE的基础,因此序列化是javaEE平台的基础
④注意: 

如果需要让某个对象支持序列化机制:则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一 否则会抛出
  NoSerializableException的异常

  • Sericalizable
  • Externalizable


ObjectInputStream 和 ObjectOutputStream 不能序列化static和transient修饰的成员;

⑤demo示例(只是为了展示基本使用步骤)

 1 /**
 2      * 对象的序列号(简单版)
 3      *
 4      * @Description
 5      * @author lixiuming
 6      * @throws IOException
 7      * @date 2021年5月15日下午2:47:12
 8      *
 9      */
10     @Test
11     public void testObjectStream() throws IOException {
12         File file = new File("object.dat");
13         FileOutputStream fi = new FileOutputStream(file);
14         ObjectOutputStream bos = new ObjectOutputStream(fi);
15         bos.writeObject(new String("我爱北京天安门"));
16         bos.close();
17     }
18 
19     /**
20      * 反向过程
21      *
22      * @Description
23      * @author lixiuming
24      * @date 2021年5月15日下午3:01:59
25      *
26      */
27     @Test
28     public void testInput() {
29         ObjectInputStream bis = null;
30         try {
31             File file = new File("object.dat");
32             FileInputStream fi = new FileInputStream(file);
33             bis = new ObjectInputStream(fi);
34             byte[] arr = new byte[1024];
35             String str = (String) bis.readObject();
36             System.out.println(str);
37         } catch (Exception e) {
38             // TODO: handle exception
39         } finally {
40             try {
41                 if (bis != null) {
42                     bis.close();
43                 }
44             } catch (IOException e) {
45                 // TODO Auto-generated catch block
46                 e.printStackTrace();
47             }
48         }
49 
50     }
View Code

升级版:

 1 /
 2       自定义类的序列化
 3       
 4       @Description
 5       @author lixiuming
 6       @date 2021年5月15日下午3:23:28
 7      
 8      /
 9     @Test
10     public void test1() {
11         ObjectOutputStream obs = null;
12         try {
13             File file = new File("Person.dat");
14             FileOutputStream fo = new FileOutputStream(file);
15             obs = new ObjectOutputStream(fo);
16             Persion persion = new Persion();
17             persion.setAge(11);
18             persion.setName("李秀明");
19             obs.writeObject(persion);
20         } catch (Exception e) {
21             // TODO: handle exception
22         } finally {
23             try {
24                 if (obs != null) {
25 
26                     obs.close();
27                 }
28             } catch (IOException e) {
29                 // TODO Auto-generated catch block
30                 e.printStackTrace();
31             }
32         }
33     }
34 
35     /
36       自定义饭序列化
37       
38       @Description
39       @author lixiuming
40       @date 2021年5月15日下午3:44:38
41      
42      /
43     @Test
44     public void test2() {
45         ObjectInputStream bis = null;
46         try {
47             File file = new File("Person.dat");
48             FileInputStream fi = new FileInputStream(file);
49             bis = new ObjectInputStream(fi);
50             Persion persion = (Persion) bis.readObject();
51             System.out.println(persion.toString());
52         } catch (Exception e) {
53             // TODO: handle exception
54         } finally {
55             try {
56                 if (bis != null) {
57                     bis.close();
58                 }
59             } catch (IOException e) {
60                 // TODO Auto-generated catch block
61                 e.printStackTrace();
62             }
63         }
64 
65     }

涉及到的类:

注意:对类的要求:

  • 需要实现接口:serializable
  • 当前类提供一个全局常量:serializableUID
  • 除了当前类需要实现serializable接口外,还必须保证其内部所有属性也必须是可序列话的 默认情况下,基本数据类型是可序列化的;

 补充:

  • ObjectOutputStream 和 ObjectInputStream不能序列化static和transient修饰的成员
public class Persion implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = -5081496688118179383L;
    private String name;
    private int age;
    private Account account;//必须实现Serializable接口

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

}

class Account implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = -3229470228130872968L;
    private double banlence;

    public double getBanlence() {
        return banlence;
    }

    public void setBanlence(double banlence) {
        this.banlence = banlence;
    }

}
View Code
  • 对象的可序列化在网络传参场景中的使用:一般在传输过程中,使用String(和基本数据类型,基本数据类型这里不讨论)来传输;
    1.  String实现了序列化;所以不需要对每个类进行实例化;
    2.  每个对象都可以转成json;(json是特殊的字符串)

6.RandomAccessFile

说明:
     1.RdomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
     2.RandomAccessFile既可以作为输入流,又可以作为输出流

  RandomAccessFile的访问模式:

  • r:以只读的方式打开
  • rw:打开以后可以读取和写入
  • rwd:打开以后可以读取和写入,同步文件内容的更新
  • rws:打开以后可以读取和写入,同步文件内容和元数据的更新;


     3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建,如果存在,则会对原有文件进行覆盖(默认情况下从头覆盖);
     4.可以通过相关操作,可以实现对文件的“插入”数据的效果;
     (应用场景,文件断点续传)

demo1以照片赋值为例

 1 @Test
 2     public void testAccessFileStream() {
 3         RandomAccessFile af = null;
 4         RandomAccessFile af2 = null;
 5         try {
 6             File file = new File("collection.png");
 7             File file2 = new File("collection22.png");
 8             af = new RandomAccessFile(file, "r");
 9             af2 = new RandomAccessFile(file2, "rw");
10             byte[] arr = new byte[1024];
11             int len = af.read(arr);
12             while (len != -1) {
13                 for (int i = 0; i < len; i++) {
14                     af2.write(arr[i]);
15                 }
16 
17                 len = af.read(arr);
18             }
19         } catch (Exception e) {
20             // TODO: handle exception
21         } finally {
22             try {
23                 if (af != null) {
24                     af.close();
25                 }
26             } catch (IOException e) {
27                 // TODO Auto-generated catch block
28                 e.printStackTrace();
29             }
30             try {
31                 if (af2 != null) {
32 
33                     af2.close();
34                 }
35             } catch (IOException e) {
36                 // TODO Auto-generated catch block
37                 e.printStackTrace();
38             }
39         }
40 
41     }
View Code

demo2关于文件操作

//对文件的操作
    @Test
    public void testAccessFileStream2() {
        RandomAccessFile af2 = null;
        try {
            File file2 = new File("accessfile.txt");
            af2 = new RandomAccessFile(file2, "rw");
            af2.seek(12);//指定写入位置(从该位置进行覆盖)
            af2.write("1234567890".getBytes());//默认情况:文件不存在,则创建,存在,则覆盖(默认从头开始覆盖)

        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            try {
                if (af2 != null) {

                    af2.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
View Code

五、使用第三方jar包实现数据读写

1.org.apache.commons.io.FileUtils实现文件的复制

(commons-io-2.8.0.jar)

demo(复制文件)

 1 package io;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 
 6 import org.apache.commons.io.FileUtils;
 7 import org.junit.Test;
 8 public class FileUtilsTest {
 9     @Test
10     public void test() {
11         File srcFile = new File("hello.text");
12         File destFile = new File("fileUtilsTest.txt");
13         try {
14             FileUtils.copyFile(srcFile, destFile);
15         } catch (IOException e) {
16             // TODO Auto-generated catch block
17             e.printStackTrace();
18         }
19         
20     }
21     
22 
23 }

2.大文件的读取:

 1 @Test
 2     public void test3() {
 3         try {
 4             JsonFactory f = new MappingJsonFactory();
 5             JsonParser jp = f.createJsonParser(new File("data_geo.txt"));//大文件的读取
 6             JsonToken current;
 7             current = jp.nextToken();
 8             if (current != JsonToken.START_ARRAY) {
 9                 System.out.println("Error: root should be object: quiting.");
10                 return;
11             }
12             while (jp.nextToken() != JsonToken.END_ARRAY) {
13                 JsonNode node = jp.readValueAsTree();
14                 // And now we have random access to everything in the object
15                 System.out.println("name: " + node.get("name").getTextValue());
16                 System.out.println("geo: " + node.get("geo").getTextValue());
17             }
18         } catch (JsonParseException e) {
19             // TODO Auto-generated catch block
20             e.printStackTrace();
21         } catch (JsonProcessingException e) {
22             // TODO Auto-generated catch block
23             e.printStackTrace();
24         } catch (IOException e) {
25             // TODO Auto-generated catch block
26             e.printStackTrace();
27         } finally {
28 
29         }
30     }

引用文件:

1 import org.codehaus.jackson.JsonFactory;
2 import org.codehaus.jackson.JsonNode;
3 import org.codehaus.jackson.JsonParseException;
4 import org.codehaus.jackson.JsonParser;
5 import org.codehaus.jackson.JsonProcessingException;
6 import org.codehaus.jackson.JsonToken;
7 import org.codehaus.jackson.map.MappingJsonFactory;
View Code

 

六、NIO.2中Path、Paths、Files类的使用

说明:早期File类的功能比较有限,不会提供异常信息;NIO2为了补补不足,引入了Paht接口,Path可以看成是File类的升级版,实际引用的资源也可以不存在;

 1 package io;
 2 
 3 import org.junit.Test;
 4 
 5 import java.io.File;
 6 import java.nio.file.Path;
 7 import java.nio.file.Paths;
 8 
 9 
10 /**
11   * 1. jdk 7.0 时,引入了 Path、Paths、Files三个类。
12  * 2.此三个类声明在:java.nio.file包下。
13  * 3.Path可以看做是java.io.File类的升级版本。也可以表示文件或文件目录,与平台无关
14  * <p>
15  * 4.如何实例化Path:使用Paths.
16  * static Path get(String first, String … more) : 用于将多个字符串串连成路径
17  * static Path get(URI uri): 返回指定uri对应的Path路径
18  * @Description        
19  * @author            lixiuming
20  * @version    
21  * @date            2021年5月15日下午8:02:08            
22  *
23  */
24 public class PathTest {
25 
26     //如何使用Paths实例化Path
27     @Test
28     public void test1() {
29         Path path1 = Paths.get("d:\\nio\\hello.txt");//new File(String filepath)
30 
31         Path path2 = Paths.get("d:\\", "nio\\hello.txt");//new File(String parent,String filename);
32 
33         System.out.println(path1);
34         System.out.println(path2);
35 
36         Path path3 = Paths.get("d:\\", "nio");
37         System.out.println(path3);
38     }
39 
40     //Path中的常用方法
41     @Test
42     public void test2() {
43         Path path1 = Paths.get("d:\\", "nio\\nio1\\nio2\\hello.txt");
44         Path path2 = Paths.get("hello.txt");
45 
46 //        String toString() : 返回调用 Path 对象的字符串表示形式
47         System.out.println(path1);
48 
49 //        boolean startsWith(String path) : 判断是否以 path 路径开始
50         System.out.println(path1.startsWith("d:\\nio"));
51 //        boolean endsWith(String path) : 判断是否以 path 路径结束
52         System.out.println(path1.endsWith("hello.txt"));
53 //        boolean isAbsolute() : 判断是否是绝对路径
54         System.out.println(path1.isAbsolute() + "~");
55         System.out.println(path2.isAbsolute() + "~");
56 //        Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径
57         System.out.println(path1.getParent());
58         System.out.println(path2.getParent());
59 //        Path getRoot() :返回调用 Path 对象的根路径
60         System.out.println(path1.getRoot());
61         System.out.println(path2.getRoot());
62 //        Path getFileName() : 返回与调用 Path 对象关联的文件名
63         System.out.println(path1.getFileName() + "~");
64         System.out.println(path2.getFileName() + "~");
65 //        int getNameCount() : 返回Path 根目录后面元素的数量
66 //        Path getName(int idx) : 返回指定索引位置 idx 的路径名称
67         for (int i = 0; i < path1.getNameCount(); i++) {
68             System.out.println(path1.getName(i) + "*****");
69         }
70 
71 //        Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
72         System.out.println(path1.toAbsolutePath());
73         System.out.println(path2.toAbsolutePath());
74 //        Path resolve(Path p) :合并两个路径,返回合并后的路径对应的Path对象
75         Path path3 = Paths.get("d:\\", "nio");
76         Path path4 = Paths.get("nioo\\hi.txt");
77         path3 = path3.resolve(path4);
78         System.out.println(path3);
79 
80 //        File toFile(): 将Path转化为File类的对象
81         File file = path1.toFile();//Path--->File的转换
82 
83         Path newPath = file.toPath();//File--->Path的转换
84 
85     }
86 
87 
88 }
View Code

 

 

 

 

 

 

 

 

 

 

 

 


     

 

posted @ 2021-05-15 20:18  啄木鸟伍迪  阅读(85)  评论(0编辑  收藏  举报
//火箭 GenerateContentList();