java编程思想读书笔记 第十八章 java I/O系统(第一篇)

时间:2022-01-13 01:55:33

1. File类
File(文件)类这个名字有一定的误导性;我们可能会认为它指代的是文件,实际上却并非如此。塔既能代表一个特定文件的名称,又能代表一个目录下的一组文件的名称。如果它指的是一个文件集,我们就可以对此集合调用list()方法,这个方法会返回一个字符数组。我们很容易就可以理解返回的是一个数组而不是某个更具灵活性的容器,因为元素的个数是固定的,所以如果想取得不同的目录列表,只需要再创建一个不同发File对象就可以了。实际上FilePath(文件路径)对这个类来说是个更好的名字。

1.1目录列表器
查看一个目录列表,可以用两种方法来使用File对象,一是调用不带参数的list()方法,便可以获得此File对象包含的全部列表;另外一个是获得一个受限列表就要通过”目录过滤器“才可以了。

1.2 目录实用工具
程序中一项常见的任务就是在文件集上执行操作,这些文件要么在本地目录中,要么遍布于整个目录树种。如果有一种工具能够为你产生这个文件集,那么它会非常有用。下面的实用工具类就可以通过使用local()方法产生的本地目录中的文件构成的File对象数组,或者通过使用walk()方法产生给定目录下的由整个目录树种所有文件构成的List。例子如下:

public final class Directory {
    public static File[] local(File dir,final String regex){
        return dir.listFiles(new FilenameFilter() {
            private Pattern pattern = Pattern.compile(regex);
            @Override
            public boolean accept(File dir, String name) {
                return pattern.matcher(new File(name).getName()).matches();
            }
        });
    }
    public static File[] local(String path,final String regex){
        return local(new File(path), regex);
    }
    public static class TreeInfo implements Iterable<File>{

        public List<File> files = new ArrayList<File>();
        public List<File> dirs = new ArrayList<File>();
        @Override
        public Iterator<File> iterator() {
            return files.iterator();
        }
        void addAll(TreeInfo other){
            files.addAll(other.files);
            dirs.addAll(other.dirs);
        }
        public String toString(){
            return "dirs:";
        }
    }
    public static TreeInfo walk(String start,String regex){
        return recurseDirs(new File(start), regex);
    }
    public static TreeInfo walk(File start,String regex){
        return recurseDirs(start, regex);
    }
    public static TreeInfo walk(File start){
        return recurseDirs(start, ".*");
    }
    public static TreeInfo walk(String start){
        return recurseDirs(new File(start), ".*");
    }
    public static TreeInfo recurseDirs(File startDir,String regex){
        TreeInfo result = new TreeInfo();
        for (File file : startDir.listFiles()) {
            if (file.isDirectory()) {
                result.dirs.add(file);
                result.addAll(recurseDirs(file, regex));
            }else {
                if (file.getName().matches(regex)) {
                    result.files.add(file);
                }
            }
        }
        return result;
    }
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println(walk("."));
        }else {
            for (String string : args) {
                System.err.println(walk(string));
            }
        }
    }
}

local()方法使用被称为listFile()的File.list()的辩题来产生File数组。可以看到,还使用了FilenameFilter。如果需要List而不是数组,你可以使用Arrays.asList()对结果进行转换。

1.3 目录的检查及创建
File对不仅仅只代表存在的文件或目录。也可以用File对象来创建新的目录或尚不存在的整个目录的路径。还可以查看文件的特性(如:大小,最后修改日期等),检查某个File对象代表的是一个文件还是一个目录,并可以删除文件。文件操作包括以下几个方法:
f.isFile()判断是否是一个文件
f.isDirectory()判断是一个文件目录
file.exists()判断文件是否存在
file.delete()删除文件
file.mkdirs()创建文件
file.getAbsolutePath()获取文件的绝对路径
file.getName()获取文件的名字

2. 输入和输出
流是个抽象的概念,它代表任何有能力产出数据的数据源对象或者是具有能力接收数据的接收端对象。“流”屏蔽了实际的I/O设备中处理数据的细节。
java类库中的I/O类分成输入和输出部分,通过继承,任何自InputStream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或者字节数组。同样,任何自OutputStream或Writer派生而来的类都含有名为write()的基本方法,用于写单个字节或者字节数组。但是我们通常不会用到这些方法,她们之所以存在是因为别的类可以使用它们,以便提供更有用的接口。因此,创建流的对象是通过叠合多个对象来提供所期望的功能。实际上,java中“流”类库让人迷惑的主要原因在于:创建单一的流却需要创建多个对象。

2.1 InputStream类型
InputStream作用是用来表示那些从不同数据源产生输入的类。这些数据源包括:
1)字节数组
2)String对象
3)文件
4)“管道”,工作方式与实际管道相似,即从一端输入,从另一端输出。
5)一个由其他种类的流组成的序列,以便我们可以将他们收集合并到一个流内。
6)其他数据源
每一种数据源都有相应的InputStream子类。另外FilterInputStream也属于InputStream。下图是InputStream类型:

java编程思想读书笔记 第十八章 java I/O系统(第一篇)

2.2 OutputStream类型
如下图所示,该类别的类决定了输出所要去往的目标:字节数组(但部署String,不过你当然可以用字节数组字自己创建)、文件或管道。

java编程思想读书笔记 第十八章 java I/O系统(第一篇)