黑马程序员—IO(二)File类、Properties类、打印流、序列流(合并流)

第一节     File类

一、概述

1、File类:文件和目录路径名的抽象表现形式

2、特点

        1)用来将文件或文件夹封装成对象

        2)方便于对文件与文件夹的属性信息进行操作

        3)File类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变

        4)File对象可以作为参数传递给流的构造函数

 

二、File对象创建

方式一:      

             File f =new File("a.txt");

        将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。

 方式二:

            File f2=newFile("c:\\abc","b.txt");

        将文件所在目录路径和文件一起传入,指定文件路径。

 方式三:

            File d=new File("c:\\abc");

             File f3=new File(d,"c.txt");

        将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。

小知识:

        File.separator表示目录分隔符,可以跨平台使用。相当于路径中的“\”(双斜杠\\在windows中表示表示转义后的分隔符,但是在linux系统中就不是)。

 

三、File类的常见方法

1、创建

        booleancreateNewFile();

        //在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立就创建文件。而且文件已经存在,会覆盖。

        boolean mkdir();//创建文件夹,只能创建一级文件夹

例:

        File dir=new File("abc");

        dir.mkdir();//创建abc这个文件夹

        boolean mkdirs();//创建多级文件夹

2、删除

        boolean delete();

        //删除文件或目录。文件存在,返回true;文件不存在或者正在被执行,返回false。    

        void deleteOnExit();//在程序退出时删除指定文件

3、判断

        boolean canExecute();//是否是可执行文件

        boolean exists();//文件是否存在

        boolean isFile();//是否是文件

        boolean isDirectory();//是否是文件夹

        boolean isHidden();//是否是隐藏文件

        boolean isAbsolute();//文件是否是绝对路径

记住:在判断文件对象是否是文件或者目录时,必须要判断该文件对象封装的内容是否存在。通过exists判断。

4、获取信息

        String getName();//获取文件名

        String getPath();

        //获取文件的相对路径(即创建的对象传入的参数是什么就获取到什么)

        String getParent();

        //获取文件父目录。返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。

        String getAbsolutePath();//获取文件的绝对路径      

        long lastModified();//返回文件最后一次被修改的时间

        long length();//返回文件长度

5、列出文件及文件过滤

        static File[] listRoots();//列出可用的文件系统根目录,即系统盘符

        String[] list();

        //列出当前目录下所有文件,包括隐藏。调用list方法的file对象必须是封装了一个目录。该目录还必须存在。

        String[]list(FilenameFilter filter);

        //返回一个字符串数组,获取目录中满足指定过滤器的文件或目录。

        //FilenameFilter:文件名过滤器,是一个接口,其中包含一个方法,accept(Filedir,String name),返回的是boolean型,对不符合条件的文件过滤掉。

        File[] listFiles();//返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹

        File[] ListFiles(FilenameFilterfilter);//返回抽象路径名数组,获取目录中满足指定过滤器的文件或目录。

四、递归

1、定义

       当函数内每一次循环还可以调用本功能来实现,也就是函数自身调用自身。这种表现形式,或者编程手法,称为递归。

2、递归注意事项

        a、限定条件。是来结束循环调用,否则是死循环。

        b、注意递归的次数,尽量避免内存溢出。因为每次调用自身的时候都会先执行下一次调用自己的方法,所以会不断在栈内存中开辟新空间,次数过多,会导致内存溢出。

例子:将一个数模2、两种不同写法的对比

public static void toBin(int num)
    {
        while (num>0)
        {
            sop(num % 2);
            num = num/2;
        }
    }
    public static void toBin(int num)
    {
        if(num>0)//退出递归的条件
        {
            toBin(num / 2);
            sop(num % 2);
        }
    }

练习:递归获取目录

练习:用String[] list(FilenameFilter filter)方法获取一个目录下所有的.java文件。 
思路:1、FilenameFilter是一个过滤器接口,用匿名内部类传入filter对象 
      2、覆写FilenameFilter接口的accept(File file,String name)方法,并判断name是否是java文件 
      3、遍历String类型数组
import java.io.*;
public class  testIO
{  
    public static void main(String[] args)
    {
        File dir = new File("e:\\download");
        
        showDir(dir,0);
    }
    
    public static void showDir(File dir,int level)
    {
        sop(dir);
        level++;

        File[] files = dir.listFiles();//获取该目录下的所有文件或文件夹

        for (int x=0;x<files.length ;x++ )
        {
            if (files[x].isDirectory()) //如果是文件夹,就递归再次进入本方法
                showDir(files[x],level);
            else
                System.out.println(getLevel(level)+files[x]);//如果是文件,就输出其路径
        }
    }

    public static void sop(Object obj)
    {
        System.out.println(obj);
    }

    public static String getLevel(int level)
    {
        StringBuilder sb = new StringBuilder();
        
        for (int x=0;x<level ;x++ )
        {
            sb.append("--");
        }
        sb.append("|");
        return sb.toString();
    }
}

递归删除目录:

删除原理: 
在windows中,删除目录从里面往外面删除的。 
既然是从里往外删除。就需要用到递归。
    public static void main(String[] args)
    {
        File dir = new File("e:\\download");
        removeDir(dir);
    }
    
    public static void showDir(File dir,int level)
    {
        sop(dir);
        level++;

        File[] files = dir.listFiles();

        for (int x=0;x<files.length ;x++ )
        {
            if (files[x].isDirectory())
                showDir(files[x],level);
            else
                System.out.println(getLevel(level)+files[x]);
        }
    }
    
    public static void deleteDir(File dir)
    {
        File[] files = dir.listFiles();//列出目录下的所有文件夹
        for (File f : files )
        {
            if(!f.isHidden() && f.isDirectory())
                removeDir(file);//删除目录里的文件或文件夹
            else
                sop(f.toString() + ":-file:" + file.delete());
        }
        System.out.println(dir+":::dir:::"+dir.delete());//删除目录  
    }
练习: 
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。建立一个java文件列表的文件。 
思路: 
     1、对指定的目录进行递归。 
     2、获取递归过程所有的java文件的路径。 
     3、将这些路径存储到集合中。 
     4、将集合中的数据写入到一个文件中。  
import java.io.*;
import java.util.*;
class ioTest2 
{
    public static void main(String[] args) 
    {
        File dir = new File("e:\\資料大全");
        List<File> list = new ArrayList<File>();
        File f = new File(dir,"javaFileList.txt");
        writeToFile(list,file);
    }
    
    public static void fileToList(File dir,List<File> list)
    {
        File[] files = dir.listFiles();
        for (File f:files )
        {
            //如果是目录 则继续获取
            if (f.isDirectory())
            {
                list.add(file.getAbsoluteFile());
                fileToList(f,list);
            }
            else if (file.getName().endsWith(".java"))//将是.java文件的绝对路径存入
                    list.add(f);
        }
    }
    //将集合元素写入到一个文本文件中
    public static void writeToFile(List<File> list,File file)
    {
        BufferedWriter bfw = null;
        try
        {
            bfw = new BufferedWriter(new FileWriter(file));
            for (File f:list )
            {
                bfw.write(f.getAbsolutePath());
                bfw.newLine();
                bfw.flush();
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException("写入文件失败");
        }
        finally
        {
            try
            {
                if(bw!=null)
                    bw.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("流资源关闭失败");
            }
        }
    }
}

第二节      Properties类

一、概述

1、Properties是Hashtable的子类,它具备Map集合的特点。而且它里面还有存储的键值对,都是字符串,无泛型定义。是集合中和IO技术想结合的集合容器。

2、特点:

        1)可用于键值对形式的配置文件

        2)在加载时,需要数据有固定的格式,常用的是:键=值

二、特有方法

1、设置

        Object setProperty(String key,String value);

        //设置键和值,调用Hashtable的方法put

2、获取

        String getProperty(String key);

        //指定key搜索value

        Set<String> stringPropertyName();

        //返回属性列表的键集,存入Set集合

3、加载流和存入流

        void load(InputStream ism);

        //从输入字节流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。

        void load(Readerreader);

        //从输入字符流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。

        voidlist(PrintStream out);//将属性列表输出到指定的输出流

        void store(OutputStreamout,String comments);

        //对应load(InputStream )将属性列表(键值对)写入输出流。comments属性列表的描述。

        void store(Writerwriter, String comments);

        //对应load(Reader)将属性列表(键值对)写入输出流。comments属性列表的描述。

示例,如何将流中的数据存储到集合中。 

 /* 
        1,用一个流和info.txt文件关联。 
        2,读取一行数据,将该行数据用"="进行切割。 
        3,等号左边作为键,右边作为值。存入到Properties集合中即可。 
 
    */
public static void saveToProp() throws IOException
    {
        BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
        String line = null;
        Properties prop = new Properties();
        while ((line=bufr.read())!=null)
        {
            String[] arr = line.split("=");
            prop.setProperty(arr[0],arr[1]);
        }
        bufr.close();
        System.out.println(prop);
    }
练习:用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。     
分析: 
写一个计数器程序。可是该计数器定义在程序中,随着该应用程序的退出,该计数器也在内存中消失了。 
所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式。键值对数据是map集合。数据是以文件形式存储。使用io技术。那么map+io——>Properties。 
 
思路:1、用读取流关联文本信息文件。如果存在则读取,如果不存在,则创建 
      2、每次运行,将文件数据存入集合中,读取值,判断次数,如果小于等于5次,则次数增加1次,如果大于则输出提示信息。 
      3、将值小于等于5次的信息数据存入文件中 
import java.util.*;  
import java.io.*;  
  
class  RunCount  
{  
    public static void main(String[] args)throws IOException   
    {  
        int count=runCount();  
        if(count>5)//如果程序被使用了超过5次,则终止使用,并提示  
        {  
            System.out.println("已达到使用次数!");  
            return ;  
        }  
        else  
            System.out.println("程序第"+count+"次Run!");  
    }  
    //获取程序运行的次数  
    public static int runCount()throws IOException  
    {  
        Properties ps=new Properties();//创建集合对象  
  
        File file=new File("info.ini");//将文件进行封装  
        if(!file.exists())//判断是否存在  
            file.createNewFile();  
        FileReader fr=new FileReader(file);//将文件于读取流进行关联  
          
        ps.load(fr);//加载流中的文件数据到集合中  
  
        int count=0;//定义计数器  
        String value=ps.getProperty("time");//获取次数值  
          
        if(value!=null)//如过值不等于null,则将其赋值给count  
        {  
            count=Integer.parseInt(value);  
        }  
        count++;//每启动一次自增  
        ps.setProperty("time",count+"");//将次数记录住集合  
  
        FileWriter fw=new FileWriter(file);  
        ps.store(fw,"");//将集合中的数据存入硬盘文件中  
          
        fr.close();//关流  
        fw.close();  
  
        return count;//返回程序启动的次数  
    }  
}  

第三节    打印流

一、概述

        1、打印流包括:PrintStream和PrintWriter

        2、该流提供了打印方法,可将各种类型的数据都原样打印。

 

二、字节打印流:PrintStream

构造方法中可接收的参数类型:

        1、File对象。File

        2、字符串路径:String

        3、字符输出流:OutputStream

 

三、字符串打印流:PrintWriter

构造方法中可接受的参数类型

        1、File对象:File

        2、字符串路径:String

        3、字节输出流:OutputStream

        4、字符输出流:Writer

示例:

import java.io.*;
class ioTest2 
{
    public static void main(String[] args) 
    {
        File dir = new File("e:\\資料大全");
        List<File> list = new ArrayList<File>();
        File f = new File(dir,"javaFileList.txt");
        writeToFile(list,file);
    }
    
    public static void saveToProp() throws IOException
    {
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        //打印流关联文件,自动刷新
        PrintWriter out = new PrintWriter(new FileWriter("a.txt",true);

        String line = null;
        while ((line=bufr.readLine())
        {
            if("over".equals(line))
                break;
            out.println(line.toUpperCase());
        }

        out.close();
        bufr.close();
    }
    
}

第四节    序列流

一、概述

1、SequenceInputStream对多个流进行合并。也被称为合并流。

2、常用构造函数

        SequenceInputStream(Enumeration<?extends FileInputStream> e)

 

二、常见合并多个流文件步骤

        1、创建集合,并将流对象添加进集合

        2、创建Enumeration对象,将集合元素加入。

        3、创建SequenceInputStream对象,合并流对象

        4、创建写入流对象,FileOutputStream关联写入文件

        5、利用SequenceInputStream对象和FileOutputStream对象读数据进行反复读写操作。

示例:

合并流 
需求:将三个文本文件中的数据合并到一个文本文件中 
思路:1、创建一个Vector集合,将三个文本文件字节流添加到集合中 
      2、创建Enumeration对象,创建SequnceInputStream对象关联Enumeration 
      3、输出流关联新文本文件 
      4、反复读写操作  
import java.util.*;  
import java.io.*;  
  
class  SequenceInputStreamDemo  
{  
    public static void main(String[] args)throws IOException  
    {  
        Vector<InputStream> ve=new Vector<InputStream>();//创建vector集合,并添加相关流对象  
        ve.add(new FileInputStream("1.txt"));  
        ve.add(new FileInputStream("2.txt"));  
        ve.add(new FileInputStream("3.txt"));  
  
        Enumeration<InputStream> en=ve.elements();//创建枚举对象  
        SequenceInputStream sis=new SequenceInputStream(en);//合并流  
  
        FileOutputStream fos=new FileOutputStream("4.txt");//关联写入文件  
          
        //反复读写操作  
        byte[] buf=new byte[1024];  
        int len=0;  
        while((len=sis.read(buf))!=-1)  
        {  
            fos.write(buf,0,len);  
        }  
          
        //关流  
        fos.close();  
        sis.close();  
    }  
} 
切割文件 
需求:将一个mp3文件按1M大小切割成几部分 
思路:1、使用文件字节流关联mp3文件 
      2、定义一个容器存储1M大小的数据,当存储满时,写入一个新文件中  
import java.util.*;  
import java.io.*;  
  
class  SplitFile  
{  
    public static void main(String[] args) throws IOException  
    {  
        //指定要切割的文件  
        File file=new File("C:\\Users\\asus\\Desktop\\苏芮 - 一样的月光.mp3");  
        //将指定文件进行切割  
        splitFile(file);  
  
        //指定要合并到的文件  
        File file1=new File("E:\\Java Study\\Practice\\day20\\splitFile\\一样的月光.mp3");  
        //将部分文件进行合并指定文件中  
        merge(file1);  
  
    }  
    //接收一个文件,将其按1M大小进行切割  
    public static void splitFile(File file)throws IOException  
    {  
        //关联要切割的文件  
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));  
          
        BufferedOutputStream bos=null;  
  
        //定义1M大小存储容器  
        byte[] buf=new byte[1024*1024];  
        int len=0,x=0;  
        while ((len=bis.read(buf))!=-1)  
        {  
            //每满1M就写入一个新文件中  
            bos=new BufferedOutputStream(new FileOutputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+(++x)+".part"));  
            bos.write(buf,0,len);  
            bos.close();//没写完一个文件要记得关流  
        }  
        //关流  
        bis.close();  
    }  
  
    //将部分文件合并为一个可执行文件  
    public static void merge(File file)throws IOException  
    {  
        //定义一个集合存储这些部分文件关联路径数据  
        ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();  
  
        for (int x=1;x<=6 ; x++)  
        {  
            al.add(new FileInputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+x+".part"));  
        }  
          
        //因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类  
        final  ListIterator<FileInputStream> it=al.listIterator();  
        Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()  
        {  
            public boolean hasMoreElements()  
            {  
                return it.hasNext();  
            }  
  
            public FileInputStream nextElement()  
            {  
                return it.next();  
            }  
        };  
  
        //关联枚举对象  
        SequenceInputStream sis=new SequenceInputStream(en);  
  
        //将合并的文件数据写入指定文件中  
        FileOutputStream fos=new FileOutputStream(file);  
          
        //定义临时存储数据的数组  
        byte[] buf=new byte[1024];  
        int len=0;  
        while((len=sis.read(buf))!=-1)  
        {  
            fos.write(buf,0,len);//写数据  
        }  
  
        //关流  
        fos.close();  
        sis.close();  
  
    }  
} 

 

posted @ 2015-07-13 22:12  tzr  阅读(218)  评论(0编辑  收藏  举报