JAVA基础--IO输入输出(File使用)17

一、 File中的方法

  1.  列举方法

 

 1 /*
 2  * 获取指定目录以及子目录下的所有文件和文件夹
 3  */
 4 public class ListFilesDemo {
 5     public static void main(String[] args) {
 6         
 7         File dir = new File("d:/test");
 8         getFiles(dir);
 9     }
10     //获取指定目录下的文件或文件夹
11     public static void getFiles(File dir) {
12         
13         //判断dir所表示的文件或文件夹是否存在
14         if( !dir.exists() ){
15             throw new RuntimeException("传递的文件或文件夹不存在");
16         }
17         //判断dir是否是目录
18         if( !dir.isDirectory() ){
19             throw new RuntimeException("传递的文件对象表示的不是一个有效的目录");
20         }
21         
22         //获取指定目录 下的文件和文件夹
23         File[] files = dir.listFiles();
24         //判断当前指定的目录Java是否有权限访问,如果没有权限会得到null
25         if( files != null ){
26             //遍历文件数组
27             for( File file : files ){
28                 //取出数组中的某个File对象
29                 if( file.isDirectory() ){
30                     //判断 成立说明当前数组中保存的某个文件对象一定是目录(文件夹)
31                     getFiles(file);
32                 }else{
33                     //判断不成立,说明当前从数组中取出的文件对象一定是文件
34                     System.out.println("正在删除的文件是:"+file.getName()+",删除的结果是:"+file.delete());
35                 }
36                 //程序如果执行到这里,说明一定将某个目录中的文件删除完成,紧接着删除这个目录
37                 System.out.println("被删除的文件夹是:"+file.getName()+",删除的结果是:"+file.delete());
38             }
39         }
40     }
41 }

 

 

  2. 递归技术

 

上述的遍历多级目录,使用到的方法在调用自己。这个技术被称为方法的递归调用。

 

递归:方法调用方法。

 

         直接递归:方法在自己的方法体中又调用自己。

 

         间接递归:A方法调用B方法,B方法调用C ...... 最后一个方法调用A方法。

 1     /*
 2  * 需求:计算1~5的和值,禁止使用循环。
 3  */
 4 public class DiGui {
 5     public static void main(String[] args) {
 6         int num = 5;
 7         int sum = getSum( num );
 8         System.out.println(sum);
 9     }
10     
11     public static int getSum(int num) {
12         
13         if( num > 1 ){
14             return num + getSum( num -1 );
15         }
16         return 1;
17     }
18 }

         递归程序注意的细节:

                   1、递归调用一定要在程序添加判断,保证递归可以停止。否则就是无限递归调用。会导致栈内存溢出。

                   2、如果递归调用有判断,但是判断的语句还没有结束就可能导致栈溢出。因此递归的次数一定不要太多。

 

  3.  文件队列

 1 /*
 2  * 使用文件队列获取指定目录以及子目录下的文件和文件夹
 3  */
 4 public class ListFilesDemo2 {
 5     public static void main(String[] args) {
 6         File dir = new File("d:/test");
 7         getFiles(dir);
 8     }
 9     //获取指定目录以及子目录下的文件和文件夹
10     public static void getFiles(File dir) {
11         //定义集合容器
12         LinkedList<File> list = new LinkedList<File>();
13         //将传递进来的文件夹先保存到集合容器中
14         list.addLast(dir);
15         //遍历集合容器
16         while( list.size() > 0 ){
17             //只要循环成立,说明集合容器中就会有文件夹存在
18             File file = list.removeFirst();
19             //获取从容器中取出的这个文件夹下的所有文件和文件夹
20             File[] files = file.listFiles();
21             //判断当前的目录Java是否有权限.判断files是否为null
22             if( files != null ){
23                 for( File f : files ){
24                     //遍历当前从容器中取出的这个文件夹下的每个文件或文件夹对象
25                     if( f.isDirectory() ){
26                         //判断成立,说明当前得到的子文件对象一定是文件夹,添加到集合中
27                         list.addLast(f);
28                     }else{
29                         ///当前的f一定是文件
30                         System.out.println(f);
31                     }
32                 }
33             }
34         }
35     }
36 }

 

 二、 文件过滤器

  1. 文件过滤器介绍

 

我们在使用list或者listFiles方法列出某个目录下的文件或者文件夹的时候,是将所有的全部列出,有时我们并不需要某个目录下的所有文件或文件夹,而是希望列出符合条件的文件或文件夹。

 

可以在使用list或listFiles方法时,给方法传递一个符合用户需求的过滤对象,这个对象可以帮助list和listFiles方法在列出目录下文件或文件夹的时候,根据传递的过滤对象将符合条件的文件和文件夹列出,不符合的就会被过滤掉。

 

在Java中提供了2个负责过滤的过滤器:

 

         FilenameFilter:文件名过滤器:是通过文件或文件夹的名称过滤

 

         FileFilter文件过滤器:通过文件或文件夹对象过滤器

  2.  FilenameFilter接口

 

 1 /*
 2  * 自己定义文件名过滤器
 3  */
 4 public class MyFilenameFilter implements FilenameFilter{
 5     //定义成员变量,记录传递的过滤的名称
 6     private String suffix;
 7     //定义构造方法,让使用者在创建过滤器对象的时候指定需要过滤的条件
 8     public MyFilenameFilter(String suffix){
 9         this.suffix = suffix;
10     }
11     /*
12      *  解释FilenameFilter中的accept方法上的两个参数
13      *      File dir : 是当前需要列举的那个目录
14      *      String name:是当前指定的目录下的文件或文件夹的名称
15      */
16     public boolean accept(File dir, String name) {
17         //System.out.println(dir + "....." + name);
18         return name.endsWith(this.suffix);
19     }
20     
21 }
22 
23 /*
24  * 演示FilenameFilter过滤器的使用
25  */
26 public class FilenameFilterDemo {
27     public static void main(String[] args) {
28         
29         //创建文件对象
30         File dir = new File("d:/test/day07_code");
31         /*
32          * 当我们在程序中使用list方法的时候,list方法会先列出当前目录下的所有文件和文件夹
33          * 然后将这些文件和文件夹传递给指定的过滤器对象,
34          * 如果过滤器中的accept方法返回的true,就认为当前这个文件或文件夹是需要保留的
35          * 如果过滤器中的accept方法返回的false,就认为当前这个文件或文件夹是不需要的
36          */
37         String[] list = dir.list(new MyFilenameFilter(".java"));
38         
39         //遍历
40         for (String s : list) {
41             System.out.println(s);
42         }
43     }
44 }

  3. FileFilter接口

 1 /*
 2  * 自定义FileFilter过滤器对象
 3  */
 4 public class MyFileFilter implements FileFilter{
 5     private String suffix;
 6     public MyFileFilter(String suffix){
 7         this.suffix = suffix;
 8     }
 9     /*
10      * 解释FileFilter中的accept方法上接收的参数
11      *     File pathname : 表示的当前目录下的那个文件或文件夹对象
12      */
13     public boolean accept(File pathname) {
14         //System.out.println(pathname.isDirectory() +".."+pathname.getName()+"..."+pathname.isFile());
15         //需要将扩展名为 .mp3的文件保留下来
16         return pathname.isFile() && pathname.getName().endsWith(this.suffix);
17     }
18 
19 }
20 
21 /*
22  * 演示FileFilter的使用
23  */
24 public class FileFilterDemo {
25     public static void main(String[] args) {
26         
27         //创建File对象
28         File dir = new File("d:/test");
29         
30         /*
31          * 获取指定目录下的文件或文件夹
32          * 
33          * 当我们调用File类中的listFiles方法,并传递以了一个FileFilter过滤器对象
34          * listFiles方法也是先将指定目录下的所有文件和文件夹获取到,
35          * 然后将这些文件或文件夹对象逐一传递给FileFilter中的accept方法。
36          * 
37          */
38         File[] files = dir.listFiles(new MyFileFilter(".java"));
39         
40         for ( File file : files){
41             System.out.println(file);
42         }
43     }
44 }

   4. 过滤器练习

需求:获取指定目录以及子目录下的文件(扩展名为.java).

 1 /*
 2  * 需求:获取指定目录以及子目录下的文件(扩展名为.java)
 3  * 
 4  */
 5 public class FilterTest {
 6     public static void main(String[] args) {
 7         
 8         File dir = new File("d:/test");
 9         getFiles(dir);
10     }
11 
12     public static void getFiles(File dir) {
13         
14         //列出指定目录下的文件和文件夹
15         File[] files = dir.listFiles( new FileFilter(){
16 
17             /*
18              * 书写过滤的条件:
19              *     如果是只过滤当前的目录,那么在书写过滤器条件的时候,
20              *     只需要判断是否是文件和文件的扩展名。
21              * 
22              *  如果需要多级目录文件获取,这时在书写过滤器的时候,
23              *  判断的条件中需要保留文件夹,和文件(扩展名必须是符合条件)
24              */
25             public boolean accept(File pathname) {
26                 return (pathname.isDirectory())  || 
27                         (pathname.isFile() && pathname.getName().endsWith(".txt"));
28             }
29             
30         } );
31         //判断
32         if( files != null ){
33             //遍历
34             for (File file : files) {
35                 if( file.isDirectory() ){
36                     getFiles(file);
37                 }else{
38                     System.out.println(file);
39                 }
40             }
41         }
42     }
43 }

 三、   IO流技术

  1. 流的分类

 

File类:它主要是操作文件和文件夹,并不能读写文件中的数据。

 

我们如果需要操作保存在文件中的数据,这时只能使用Java中提供的IO流对象。

 

   

 

IO:Input   Output。

 

IO流:它是使用Java中提供的众多的对象,和文件中的数据进行交互。

 

 

 

IO流如果按照操作数据的方向:

 

         输入流:Input,读取数据。

 

         输出流:Output,写出数据。

 

 

 

IO流如果按照操作的数据类型:

 

         字节流:它全部是以字节形式操作(读写)的数据

 

         字符流:全部是以字符的形式操作(读写)数据

 

 

 

上课以数据类型分类:现讲字节流,再讲字符流。

 

         字节流和字符流它们对文件中的数据操作规律是一致的。主要会一种,其他的都可以照着模版代码进行抄写。

  2. 字节流介绍

任何数据在电子设备中存储的方式都是二进制形式(字节)。我们就可以直接以字节方式读取文件中的数据,或者以字节的方式给文件中写数据。

字节流:

         字节输入流:它是负责以字节的方式从文件中读取数据。在程序中我们会获取到读取的字节数据。

         字节输出流:它是负责以字节的方式将程序(内存)中的数据写到文件中。

  3.  字节输出流

 

OutputStream:它是所有字节输出流的超类(基类、根类)。它中肯定定义了应该如何将字节写到底层文件中的最基本(共性)的方法。

使用Java程序操作Java以外的其他数据(数据库,硬盘,网络,其他语言开发的程序),首先需要让我们的Java程序和其他的资源平台获取连接(关联),在这个连接中进行数据的交互。交互结束之后一定要记住将彼此之间的连接断开。因此我们使用Java中的IO流技术操作其他设备上的数据,这时操作完一定要记得调用close方法。

write(byte[] b) 将指定的字节数组中的全部数据写到底层指定的设备中。

write(byte[] b , int off , int len) 将指定的字节数组中的数据从off位置开始,共计写出len个。

write(int b) 将int类型数据中的最低位一个字节写出。

  4.  文件字节输出流

FileOutputStream:它是专门负责将字节数据写到文件中。

        

 1 /*
 2  * 演示字节输出流
 3  *   使用输出流,往出写数据的时候,如果指定的文件不存在,
 4  *   这时输出流会自动的在指定的目录下创建这个文件,并将数据写到文件中。
 5  *   
 6  *   使用输出流的时候,文件不存在会创建,如果文件存在,会覆盖。原来文件中的数据全部丢失。
 7  */
 8 public class FileOutputStreamDemo {
 9     public static void main(String[] args)throws IOException {
10         method3();
11     }
12     // write(byte b)
13     public static void method3() throws IOException {
14         //创建负责写字节数据的流对象
15         FileOutputStream fos = new FileOutputStream("d:/aa.txt");
16         /*
17          * OutputSteam它写出的是字节数据,字节数据的范围是-128到127之间。
18          *  其中提供的write(int b) 它本质只能写一个字节,但是接收的int类型的数据
19          *   int类型的数据在内存中共计占用4个字节,write方法它其实只能将4个字节中
20          *   最低一位上的那个字节数据写到文件中。
21          *   
22          *   97 : 0000 0000 0000 0000 0000 0000 0110 0001
23          *   353:0000 0000 0000 0000 0000 0001 0110 0001
24          *       
25          */
26         fos.write(97);
27         fos.write(353);
28         
29         fos.close();
30     }
31     //write(byte[] b , int off , int len)
32     public static void method2() throws IOException {
33         
34         //创建负责写字节数据的流对象
35         FileOutputStream fos = new FileOutputStream("d:/aa.txt");
36         
37         //创建字节数组
38         byte[] b = {65,66,67,68,69};
39         //调用写的方法写数据
40         fos.write(b , 1 , 2);
41         
42         //关闭流对象
43         fos.close();
44         
45     }
46     //演示 write(byte[] b);
47     public static void method() throws IOException {
48         
49         //创建负责写字节数据的流对象
50         FileOutputStream fos = new FileOutputStream("d:/aa.txt");
51         
52         //创建字节数组
53         byte[] b = {65,66,67,68,69};
54         //调用写的方法写数据
55         fos.write(b);
56         
57         //关闭流对象
58         fos.close();
59     }
60 }

  5.  追加数据和换行

 1 /*
 2      * 文件写字符串数据,并换行
 3      */
 4     public static void method5() throws IOException {
 5 
 6         FileOutputStream fos = new FileOutputStream("d:/aa.txt",true);
 7         
 8         //获取操作系统支持的换行符
 9         String line_separator = System.getProperty("line.separator");// \r\n
10         String s = "Java基础正在学习IO技术"+line_separator;
11         
12         fos.write(s.getBytes());
13         
14         fos.close();
15     }
16     /*
17      * 在文件的末尾追加数据
18      * FileOutputStream(String name, boolean append)
19      *     如果创建FileOutputStream的时候,在构造方法中指定的boolean值为true
20      *     这时需要关联的文件如果不存在,它会创建,
21      *     如果已经存在,并且其中有数据,会在原来文件的末尾继续追加数据
22      */
23     public static void method4() throws IOException {
24         
25         FileOutputStream fos = new FileOutputStream("d:/aa.txt",true);
26         
27         fos.write(101);
28         fos.write(102);
29         fos.write(103);
30         fos.write(104);
31         
32         //关流
33         fos.close();
34     }

  6.  输出流练习

 1 /*
 2  * 需求:将指定目录和子目录下的指定扩展名(.java)的文件所在路径写到一个文件中,形成一个文件清单。
 3  * 分析:
 4  *         获取符合条件的文件,然后将其路径得到。再使用输出流写到文件中即可
 5  */
 6 public class FileOutputStreamTest {
 7     public static void main(String[] args) throws IOException {
 8         
 9         File dir = new File("d:/test");
10         FileOutputStream fos = new FileOutputStream("d:/文件清单.txt");
11         getListFile(dir,fos);
12         fos.close();
13     }
14     //获取指定目录下的文件清单
15     public static void getListFile(File dir ,FileOutputStream fos) throws IOException {
16         
17         File[] files = dir.listFiles( new FileFilter(){
18             public boolean accept(File pathname) {
19                 return (pathname.isDirectory()) || 
20                         (pathname.isFile() && pathname.getName().endsWith(".avi"));
21             }
22         } );
23         //判断
24         if( files != null ){
25             for (File file : files) {
26                 if( file.isDirectory() ){
27                     getListFile(file,fos);
28                 }else{
29                     //一定是文件
30                     System.out.println(file);
31                     String path = file.getAbsolutePath() + System.getProperty("line.separator");
32                     fos.write(path.getBytes());
33                 }
34             }
35         }
36     }
37 }

  7.  字节输入流

InputStream:它是字节输入流的超类(基类、根类),它中定义的是字节输入流如何读取字节数据的方法。

所有输入流:它们都有read方法,负责从底层读取数据的。如果读取到文件末尾统一返回的都是-1。

 

int read() 这个方法调用一次,就会从底层文件中获取一个字节数据,并返回这个字节数据。

int read(byte[] b) 调用一次,会从底层文件中读取若干个字节数据,并将这些字节数据存储在byte数组中,每次都是从数组的零位置开始往后存储。返回的int值表示的是给byte数组中真正存储的字节个数。

 

int read(byte[]b , int off , int len) 调用一次,从底层读取若干字节数据,将数据存储在b数组中,但是是从off位置开始存储,共计只能存储len个。返回的int值表示是的是给数组中存储的字节个数。

   8.   文件字节输入流

FileInputStream:它是专门负责从文件中读取字节数据。

 1 /*
 2  * 演示字节输入流
 3  */
 4 public class FileInputStreamDemo {
 5 
 6     public static void main(String[] args) throws IOException {
 7         method3();
 8     }
 9     //一次读取多个字节数据
10     public static void method3() throws IOException {
11         //创建输入流对象和需要被读取的文件进行关联
12         FileInputStream fis = new FileInputStream("d:/aa.txt");
13         /*
14          * 定义数组充当临时的容器,存储每次从文件中读取到的若干个字节数据。
15          * 一般定义的数组如果是存储读取到的数据,这个数组一般会是1024的整数倍
16          */
17         byte[] buf = new byte[1024];
18         //定义变量,记录每次给数组中存储的字节个数
19         int len = 0;
20         //使用循环读取数据
21         while( ( len = fis.read( buf ) ) != -1 ){
22             /*
23             for( int i = 0 ; i < len ; i++ ){
24                 System.out.print(buf[i]+" ");
25             }
26             */
27             System.out.println(new String( buf , 0 , len ));
28         }
29         
30         //关流
31         fis.close();
32     }
33     //使用循环读取文件中的数据 ,一次读取一个
34     public static void method2() throws IOException {
35         
36         //创建输入流对象和需要被读取的文件进行关联
37         FileInputStream fis = new FileInputStream("d:/aa.txt");
38         //定义变量记录每次读取到的字节数据
39         int ch = 0;
40         //使用while循环读取数据
41         while( ( ch = fis.read( ) ) != -1 ){
42             System.out.println(ch);
43         }
44         //关流
45         fis.close();
46     }
47     //演示 read()
48     public static void method() throws IOException {
49         
50         //创建输入流对象和需要被读取的文件进行关联
51         FileInputStream fis = new FileInputStream("d:/aa.txt");
52         
53         //读取字节数据
54         System.out.println(fis.read());
55         System.out.println(fis.read());
56         System.out.println(fis.read());
57         System.out.println(fis.read());
58         
59         //关流
60         fis.close();
61     }
62 }

 9.  复制文件练习

 1 /*
 2  * 需求:复制指定的文件到指定的目录下
 3  * 
 4  */
 5 public class CopyFileTests {
 6     public static void main(String[] args) throws IOException{
 7         copyFile2();
 8     }
 9     //使用数组复制
10     public static void copyFile2() throws IOException{
11 
12         //定义输入流读取文件
13         FileInputStream fis = new FileInputStream("d:/1.avi");
14         //定义输出流写文件
15         FileOutputStream fos = new FileOutputStream("c:/1.avi");
16         
17         //在开始复制文件之前获取系统的时间
18         long start = System.currentTimeMillis();
19         
20         //保存每次读取的字节个数
21         int len = 0;
22         /*
23          * 定义字节数组保存数据
24          * 8二进制 = 1字节
25          * 8bit = 1Byte
26          * 1024B = 1KB
27          * 1024KB = 1MB
28          * 1024MB = 1GB
29          * 1024GB = 1TB
30          * 1024TB = 1PB
31          */
32         byte[] buf = new byte[8192];
33         //使用循环读取数据
34         while( ( len = fis.read( buf ) ) != -1 ){
35             //使用输出流写到文件中
36             fos.write( buf, 0 , len );
37         }
38         
39         //循环结束,数据已经复制完成
40         long end = System.currentTimeMillis();
41         System.out.println("复制文件所用时间:"+(end - start));
42         
43         //关流
44         fis.close();
45         fos.close();        
46     }
47     //演示 一次读取一个字节的方式复制
48     public static void copyFile() throws IOException{
49         
50         //定义输入流读取文件
51         FileInputStream fis = new FileInputStream("d:/1.mp3");
52         //定义输出流写文件
53         FileOutputStream fos = new FileOutputStream("c:/1.mp3");
54         
55         //在开始复制文件之前获取系统的时间
56         long start = System.currentTimeMillis();
57         
58         //保存每次读取的字节数据
59         int ch = 0;
60         //使用循环读取数据
61         while( ( ch = fis.read() ) != -1 ){
62             //使用输出流写到文件中
63             fos.write(ch);
64         }
65         
66         //循环结束,数据已经复制完成
67         long end = System.currentTimeMillis();
68         System.out.println("复制文件所用时间:"+(end - start));
69         
70         //关流
71         fis.close();
72         fos.close();
73     }
74 }

 

posted @ 2017-10-23 14:55  最苦逼的程序猿  阅读(307)  评论(0编辑  收藏  举报