zoukankan      html  css  js  c++  java
  • day20(下)_IO流5(递归穷举与删除,Properties,PrintStream,PrintWriter,SequenceInputStream)

    1.对目录和文件递归穷举

    /*
    列出指定目录下的文件或者文件夹,包含子目录中的内容
    也就是列出目录下所有的内容
    例如:new File(d:\\);
     在d盘下还有一个abc目录而abc下还有文件和目录,而用list()方法只能获取到
     d盘下的文件和目录
    */
    package filedemo;
    import java.util.Arrays;
    import java.io.File;
    
    class FileFilterDemo2{
        /*
         采用了递归(重复调用使用自身功能),即首先遍历该目录下所有文件/目录
         一旦遍历到目录,在调用自身进行遍历.
       */
         public static String level(int n){
          StringBuilder sb=new StringBuilder();
          sb.append("|-");
          while((n--)!=0)
            sb.insert(0," ");//不断的向"|-"前插入空格
          return sb.toString();
         }
         public static void getFiles(File f,int level){
        
          System.out.println(level(level)+f);
          level++;//递归调用为下一级目录
          File[] dirFiles=f.listFiles();//获取到该目录下所有的文件和目录,其中File对象都采用File(File parent,String child)构造
          if(dirFiles==null||dirFiles.length==0)//说明传入的pathName不表示目录或目录为空,那么不需要遍历
              return;
          else
             for(File file : dirFiles){
                 if(file.isDirectory())//当file中的对象的child依然是目录接着遍历
                    getFiles(file,level);
                 else
                    System.out.println(level(level)+file);
                }
           
          
    }
         
         public static void main(String[] args){
         
            getFiles(new File("f:\\a"),0);
         }
    }

    _thumb1

    关于递归注意事项:

    /*
    递归注意:
      一定要有出口(也就是限定条件),不然相当于死循环
      递归次数过多,会导致OutOfMemoryError(内存溢出)
    */
    class RecursionTest{
      /*十进制->二进制*/
      public static void toBin(int num){
     
       if(num>0)
       {
          toBin(num/2);
          System.out.print(num%2);
       }
      }
      
      /*求前n项和*/
      public static int getSum(int n){
        if(n==1)
         return 1;
        else
          return n+getSum(n-1);
     
      }
      public static void main(String[] args){
         toBin(10);
         System.out.println("\n"+getSum(80000));//不断在内存中开辟空间->OutOfMemoryError(内存溢出) 
      }
    }

    2.递归删除指定目录:

    /*
     删除一个带内容的目录
     删除原理:
        在windows中,删除目录从目录里面往外删除
     从里往外删->递归
    */
    package filedemo;
    import java.io.File;
    class RemoveDir{
        public static void removeDir(File f){
         File[] allFile=f.listFiles();
         if(allFile==null||allFile.length==0)//空文件夹/文件 直接删除
           System.out.println(f.delete());
         
          else{//遍历到最内层->删除,删除完内层->逐步往外删
            for(File files : allFile){
               if(files.isFile())
                  System.out.println(files.delete());
               else
                  removeDir(files);
            }
             System.out.println(f.delete());//当for执行完,说明该目录下文件已经全部删除,需要删除该目录 
          }
        }
        public static void main(String[] args){
           removeDir(new File("h:\\a"));
        }
    }

    对于运行结果,(依然是上面遍历的测试目录)会删除9次,会有9个boolean值并且必须都为true,否则可能为同一个文件/目录多次删除

    _thumb

    3.File练习:

    /*
     获取到指定目录中所有java文件的路径,并输出到一个文件中.
    思想:
    ①对目录进行递归搜索
    ②对于文件只要以.java结尾文件
    ③把.java文件路径存入ArrayList集合中.
    
    */
    package filedemo;
    import java.io.File;
    import java.io.IOException;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.util.ArrayList;
    import java.util.List;
    class JavaFilesList{
      
      public static void getJavaFiles(File dir,List<File> list){
          File[] files=dir.listFiles();
          
          if(files!=null && files.length!=0)
             for(File f : files)
                if(f.isDirectory())
                    getJavaFiles(f,list);
                else
                  if(f.getName().endsWith(".java"))
                     list.add(f);
                    
      }
      
      public static void writeFile(List<File> list,String javaListFile){
        BufferedWriter bfw=null;
        File[] javaFiles=list.toArray(new File[list.size()]);//集合转数组
        try{
        bfw=new BufferedWriter(new FileWriter(javaListFile));
        for(File f : javaFiles){
          bfw.write(f.getAbsolutePath());//获取到绝对路径写入,list存入File对象不一定封装的是绝对路径,可能是相对路径
          bfw.newLine();
          bfw.flush();
        }
        bfw.write("一共"+list.size()+"个java文件");
       }
       catch(IOException e){
         throw new RuntimeException("写文件异常");
       }
       finally{
        try{
         if(bfw!=null)
             bfw.close();
        }
        catch(IOException e){
           throw new RuntimeException("关闭流异常");
        }
        try{
        Runtime.getRuntime().exec("notepad.exe "+javaListFile);//写完后,自动用记事本打开查看内容
        }
        catch(IOException e){
          e.printStackTrace();
        }
       }
      }
      public static void main(String[] args){    
        
        List<File> list=new ArrayList<File>();
        getJavaFiles(new File("g:\\JavaCode"),list);
        System.out.println(list.size());
        
        writeFile(list,"f:\\JavaFiles.txt");//写入文件
        }
    }

    将制定文件夹从源路径复制到目的路径下:

    /*
    采用递归方法遍历文件夹中的内容
    例如:C:\s\abc->d:\ 将abc文件夹及文件夹的所有文件/文件夹拷贝到d盘下
                  AbsolutePath
    abc         
       1.txt      ->d:\abc
       def        ->d:\abc\ def
         2.txt    ->d:\abc\def\ 2.txt
         ghk      ->d:\abc\def\ ghk
           3.txt  ->d:\abc\def\ghk\ 3.txt
       mnl        ->d:\abc\mnl
    */
    /*
    递归过程:
     1.                      
      src: c:\s\abc 
      dest: d:\
      
      dest<-d:\abc 创建abc
      
      copyFile(c:\s\abc\1.txt,d:\abc\1.txt)
      copyDir(c:\s\abc\def,d:\abc)
    2.
      src:c:\s\abc\def
      dest:d:\abc
      
      dest<-d:\abc\def 创建def
    
      copyFile(c:\s\abc\def\2.txt,d:\abc\def\2.txt)
      copyDir(c:\s\abc\def\ghk,d:\abc\def)
    3....
    */
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    class CopyDirectory{
     
     public static void copyFile(File src,File dest)throws IOException{
      FileInputStream fis=new FileInputStream(src);
      FileOutputStream fos=new FileOutputStream(dest);
      byte[] byteArr=new byte[1024*1024];
      int bytes=0;
      while((bytes=fis.read(byteArr))!=-1)
          fos.write(byteArr,0,bytes);
      fis.close();
      fos.close();
     }
     public static void copyDir(File src,File dest)throws IOException{
      File[] files=src.listFiles();
      dest=new File(dest.getPath()+"\\"+src.getName());//例如:第一次 创建 d:+\+abc
      dest.mkdir();                               //     第二次 创建 d:\abc +\+ def
      
      for(File f : files)
        if(f.isFile())
          copyFile(new File(f.getAbsolutePath()),new File(dest.getPath()+"\\"+f.getName()));//例如:当遍历到1.txt时 
                                                                                          //C:\s\abc\1.txt,d:\abc\1.txt
        else//对于文件夹操作
          copyDir(new File(f.getAbsolutePath()),dest);//例如:当遍历到def时
                                                     //C:\s\abc\def,d:\abc
        
     } 
     public static void main(String[] args)throws IOException{
      
      copyDir(new File("C:\\s\\abc"),new File("d:\\"));//abc文件夹以及文件夹中的内容拷贝到D盘下
                                                 
      
      System.out.println(new File("d:\\def\\"+"\\"+"\\"+"abc").getPath());
      System.out.println(new File("d:\\def\\"+"abc"));
    /*
    以上两者结果相同(d:\def\abc),也就是说文件系统中会去除多余的\,但是d:\\与d:结果不同,一个为d:\\,一个为d:
    */
     }
    
    }

    4.Properties类方法:

    /*
    在System类中的获取系统属性用到Properties
    
    Properties 类表示了一个持久的属性集。
    Properties 可保存在流中或从流中加载。
    属性列表中每个键及其对应值都是一个字符串。 
    
    该集合是和IO技术相结合的集合容器
    该对象特点:可以用于键值对形式的配置文件(.ini)
    在加载数据时,需要数据有固定格式:Key=Value
    */
    package propertydemo;
    import java.util.Properties;
    import java.util.Set;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.BufferedReader;
    import java.io.IOException;
    class PropertiesDemo{
        
        /*
        自定义方法将文件中的数据存储到Properties集合中
        该文件中的数据是以键值对形式存在
        例如:info.txt: 
        zhangsan=18
        lisi=25
        ...
        */
        public static void storeInProperties()throws IOException{
         BufferedReader bfr=new BufferedReader(new FileReader("info.txt"));
         Properties pro=new Properties();
         String line=null;
         while((line=bfr.readLine())!=null)
          
             if(!line.startsWith("#")){//注释信息不再加入集合
             String[] keyValue=line.split("=");//以"="分割
             pro.setProperty(keyValue[0],keyValue[1]); 
          }
         
         System.out.println(pro);
         bfr.close();
        }
        
        
        /*
        利用Properties中的load方法完成
         void load(InputStream inStream) 
              从输入流中读取属性列表(键和元素对)。 
         void load(Reader reader) 
              按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
              
        */
        public static void storeInProperties_2()throws IOException{
          FileReader fr=new FileReader("info.txt");
          Properties pro=new Properties();
          pro.load(fr);
          System.out.println(pro);
          pro.list(System.out);// void list(PrintStream out)
                                //将属性列表输出到指定的输出流。
         
         /*
         此时如果改变了键值对信息,但是改变后的信息
         依然在内存中,如果想把改变反映到文件中,需要用到
         store方法
         */
         pro.setProperty("zhangsan","30");
         System.out.println(pro);
         FileWriter fw=new FileWriter("info.txt");
         pro.store(fw,"heihei");//heihei为注释信息
                          //在文件中为#heihei
         fr.close();
         fw.close();
        }
        
        
        
        /*Properties存储和获取方法*/
        public static void propertiesMethodDemo(){
            Properties prop=new Properties();
            prop.setProperty("zhang","15");//底层在使用HashTable<Object,Object>的put方法
            prop.put("li","30");
            System.out.println(prop);
            
            Set<String> names=prop.stringPropertyNames();//返回Key的set集合
            for(String n : names)
              System.out.println(n+"="+prop.getProperty(n));
        
        }
        
        public static void main(String[] args)throws IOException{
          propertiesMethodDemo();
          System.out.println();
          
          storeInProperties();
          System.out.println();
          storeInProperties_2();
    
        } 
    }

    Properties_thumb

    5.Properties的load与store练习:

    /*
    需求:用于记录应用程序运行次数.如果使用次数已到,那么
         给出注册提示.
    分析:
      很容易想到的是:计数器
      可是该计数器
    用程序的退出,该计数器也在内存中消失了
    下一次在启动该程序,又重新开始从0计数.
    这样不是所需要的
    
    程序即使结束,该计数器的值也存在
    下次程序启动会先加载该计数器的值
    并+1后重新存储起来
    
    所以需要建立一个配置文件.用于记录软件使用次数
    
    该配置文件使用键值对的形式
    这样便于阅读数据,并操作数据
    
    键值对数据是map集合.
    数据是以文件形式存储,使用io技术
    那么map+io-->properties
    
    配置文件可以实现应用程序数据共享
    */
    package propertiestest;
    import java.util.Properties;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.File;
    class PropertiesTest{
     /*每次程序运行获取使用次数(counts),并在获取完之后,++counts存入到配置文件中*/
     public static void checkCounts()throws IOException{ 
      File f=new File("set.ini");
      Properties pro=new Properties();
     if(!f.exists())//文件第一次不存在需要创建
       f.createNewFile();
     FileReader fr=new FileReader(f);
     pro.load(fr);
     
     int count=0;
    String value=pro.getProperty("counts");
    if(value!=null)//新建文件中没有counts,此时不再获取,只写
        count=Integer.parseInt(pro.getProperty("counts"));
    
    if(count>=3){//该软件只能够使用三次
            System.out.println("免费次数已用完");
            return;//>=3不再写入直接返回
     }
    
    FileWriter fw=new FileWriter(f);
    pro.setProperty("counts",(++count)+"");
    pro.store(fw,"number of use"); 
    fr.close();
    fw.close();
    /*
     关于pro.store():
        所有写入各个项后,刷新输出流(内部在把属性集写入输出流后调用了flush)
        此方法返回后,输出流仍保持打开状态。 
        但没有关闭写入流
    */
    
    }
    
    public static void main(String[] args)throws IOException{
       checkCounts();
     }
    }
    /*
    注意:①配置文件不存在,需要创建
         ②需要写入键值对
         
    */

    6.PrintStream与PrintWriter

    /*
    打印流:
     该流提供了打印方法,可以将各种数据类型的数据都原样打印
    字节打印流:PrintStream
     PrintStream(File file) 
      file-
        同下
     PrintStream(String fileName) 
     fileName -
     要用作此打印流目标的文件名称。
     如果存在该文件,则将其大小截取为零;
     否则,创建一个新文件。将输出写入文件中,并对其进行缓冲处理。 
    
     PrintStream(OutputStream out) 
    
    字符打印流:PrintWriter
    PrintWriter(File file) 
    PrintWriter(OutputStream out)
    根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。此便捷构造方法创建必要的中间 OutputStreamWriter,后者使用默认字符编码将字符转换为字节。
      
    PrintWriter(String fileName) 
    PrintWriter(Writer out)//比PrintStream多了一个可以接收字符输出流的构造函数
    */
    package printdemo;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.IOException;
    import java.io.PrintStream;
    import java.io.PrintWriter;
    import java.io.FileWriter;
    class PrintStreamDemo{
        public static void main(String[] args)throws IOException{
         BufferedReader bufr =new BufferedReader(new InputStreamReader(System.in));
         //PrintWriter out=new PrintWriter(System.out);//PrintWriter通用性比较强,在写入流后,需要刷新
         /*
              System.out在内部会被封装为new BufferedWriter(new OutputStreamWriter(System.out))
         */
         //PrintWriter out=new PrintWriter(System.out,true);//autoFlush-boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区,下面由于用到println所以可以不用out.flush
           PrintWriter out=new PrintWriter(new FileWriter("PrintWriter.txt"),true);//true含义同上,这样写可以把new FileWriter中的数据刷新到文本中,而不用在out.flush  
                           
         String line=null;
         while((line=bufr.readLine())!=null){
             out.println(line);//将值打印初始化的流对象中
             //out.flush();//刷新的是初始化时的流对象
         }
         bufr.close();
         out.close();
        }
    }

    7.SequenceInputStream:

    /*
    SequenceInputStream(顺序输入流):
        表示其他输入流的逻辑串联。
        它从输入流的有序集合开始,
        并从第一个输入流开始读取,
        直到到达文件末尾,
        接着从第二个输入流读取,
        依次类推,直到到达包含的最后一个输入流的文件末尾为止。 
    该类的由来:
      例如:
      已知:四个文件:src1.txt,src2.txt,src3.txt,dest.txt;
      需求:把前三个文件中数据写入到dest.txt中
      分析:
       src1.txt--->FileReader("src.txt")--->FileWriter("dest.txt",true)-->dest.txt
       src2.txt,src3.txt同理    
       每个源和目的需要单独的IO流对象操作,非常麻烦
     SequenceInputStream作用:对多个源依次操作,更加方便.
    
    
    */
    package sequenceinputstream;
    import java.io.*;
    import java.util.*;
    class SequenceDemo{
        public static void main(String[] args)throws IOException{
        /*
        SequenceInputStream(Enumeration<? extends InputStream> e) 
        该构造函数形参为枚举->集合Vector<E>的elements返回Enumeration<E>
        */    
         Vector<FileInputStream> vector=new Vector<FileInputStream>();
         vector.add(new FileInputStream("f:\\src1.txt"));
         vector.add(new FileInputStream("f:\\src2.txt"));
         vector.add(new FileInputStream("f:\\src3.txt"));
         Enumeration<FileInputStream> en=vector.elements();
         SequenceInputStream sis=new SequenceInputStream(en);
         BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("f:\\dest.txt"));
         //FileOutputStream fis=new FileOutputStream("f:\\dest.txt");
         int aByte=0;
         //byte[] b=new byte[1024];
        
         while((aByte=sis.read())!=-1){
            bufos.write(aByte);
            bufos.flush();
         }
         /*
         int bytes;
         while((bytes=sis.read(b))!=-1)
            fis.write(b,0,bytes); 
          }
          */
          bufos.close();
          sis.close();
    
        
       }
    }

    文件切割和合并综合练习:

    /*
    切割文件:其实就是一个源(该文件)对应多个目的(多个碎片文件)
    切割
        ①需要一个输入流对象关联该文件
        ②为了控制每次读取大小,自定义一个缓冲(数组)
        ③循环读取,每次读取将读取的数据,通过输出流写入一个文件中,直至源文件末尾(-1)
    合并
        多个源对应一个目的,这里可以采用SequenceInputStream
    */
    
    import java.io.FileInputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.io.SequenceInputStream;
    import java.util.Enumeration;
    import java.util.Iterator;
    class SplitFileTest{
       /*当文件不太大时,指定的缓冲区可以为分割的文件大小*/
       public static void splitFile_1(String file)throws IOException{
        /*以切割图片为例*/
       FileInputStream fis=new FileInputStream(file);
       byte[] b=new byte[1024*1024];//每次最多分割1MB
       FileOutputStream fos=null;
       int bytes=0,count=1;
       while((bytes=fis.read(b))!=-1){
          fos=new FileOutputStream("f:\\part"+(count++)+".part");//每次新建一个流对象关联一个新的文件  
          fos.write(b,0,bytes); 
          fos.close();//每次循环关闭上次的流对象
       }
       fis.close();
     }
     /*
    当文件特别大(例如2GB),而需要按400MB分割,不建议定义400MB缓冲区,定义小点缓冲区40MB,使切割文件满足制定大小*/
      public static File[] splitFile_2(File f)throws IOException{
       FileInputStream fis=new FileInputStream(f);
       byte[] byteArr=new byte[1024*1024];
       ArrayList<File> arrList=new ArrayList<File>();
       int bytes=0;
      int count=0;
      File wf=null;
      FileOutputStream fos=null;
      while((bytes=fis.read(byteArr))!=-1){
         if(wf==null||wf.length()==2*1024*1024){
            if(fos!=null)
                fos.close();//关闭与上一个文件相关联的写入流对象
             wf=new File("C:\\Users\\ZhangHongQ\\Desktop\\java复习\\"+(++count)+".part");
             arrList.add(wf);
             fos=new FileOutputStream(wf);
         }
         fos.write(byteArr,0,bytes);
      }
      fis.close();
      return arrList.toArray(new File[arrList.size()]);
     }
      
      /*对以上分割的文件进行合并*/
      public static void mergeFile(File[] file)throws IOException{
        ArrayList<FileInputStream>al=new ArrayList<FileInputStream>();
        for(File f : file)
          al.add(new FileInputStream(f));
        final Iterator<FileInputStream>it=al.iterator();
        SequenceInputStream sis=new SequenceInputStream(new Enumeration<FileInputStream>(){
         public boolean hasMoreElements(){
           return  it.hasNext();
         }
         public FileInputStream nextElement(){
         
           return it.next();
         }
        });
        FileOutputStream fos=new FileOutputStream(new File("C:\\Users\\ZhangHongQ\\Desktop\\java复习\\Bandari.mp3"));
        int aByte=0;
        while((aByte=sis.read())!=-1)
          fos.write(aByte);
        sis.close();
        fos.close();
      }
      public static void main(String[] args)throws IOException{
        
        File[] file=splitFile_2(new File("F:\\SONG\\Bandari - 爱尔兰风笛.mp3"));//例如:8.93MB的MP3文件
        System.out.println(Arrays.toString(file));//2MB 2MB 2MB 2MB 934KB
        
        mergeFile(file);
      }
    }
  • 相关阅读:
    View.VISIBLE、INVISIBLE、GONE的区别
    Android中TextView内容过长加省略号
    Android 读取SIM卡参数
    java分布式通信系统(J2EE分布式服务器架构)
    Java分布式处理技术(RMI,JDNI)
    Java分布式缓存框架
    spring
    Apache与Nginx的优缺点比较
    Java如何获取文件编码格式
    java 乱码问题-Dfile.encoding=UTF-8
  • 原文地址:https://www.cnblogs.com/yiqiu2324/p/3108795.html
Copyright © 2011-2022 走看看