Java I/O

一、File类

1. File

File(文件)类这个名字有一定的误导性,我们可能认为它指代的是文件,实际上却并非如此,它技能代表一个特定文件的名称,又能代表一个目录下的一组文件的名称,如果它指定的是一个文件集,我们就可以对此集合调用list()方法,这个方法会返回一个字符数组。

class DirFilter implements FilenameFilter {
    private Pattern pattern;

    public DirFilter(String regex) {
        pattern = Pattern.compile(regex);
    }

    @Override
    public boolean accept(File dir, String name) {
        return pattern.matcher(name).matches();
    }
}

/**
 * @Author ZhangGJ
 * @Date 2020/12/04 07:51
 */
public class DirList {
    public static void main(String[] args) {
        /**
         * "."代表的路径:当前目录,项目所处的目录
         */
        File path = new File(".");
        String[] list;
        if (args.length == 0) {
            list = path.list();
        } else {
            list = path.list(new DirFilter(args[0]));
        }
        Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
        for (String dirItem : list) {
            System.out.println(dirItem);
        }
    }
}

匿名内部类版本:

/**
 * @Author ZhangGJ
 * @Date 2020/12/04 07:53
 */
public class DirList2 {
    public static FilenameFilter filter(final String regex) {

        return new FilenameFilter() {
            private Pattern pattern = Pattern.compile(regex);

            @Override
            public boolean accept(File dir, String name) {
                return pattern.matcher(name).matches();
            }
        };
    }

    public static void main(String[] args) {
        File path = new File(".");
        String[] list;
        if (args.length == 0) {
            list = path.list();
        } else {
            list = path.list(filter(args[0]));
        }
        Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
        for (String dirItem : list) {
            System.out.println(dirItem);
        }
    }
}

更进一步:

/**
 * @Author ZhangGJ
 * @Date 2020/12/04 07:53
 */
public class DirList3 {
    public static void main(final String[] args) {
        File path = new File(".");
        String[] list;
        if (args.length == 0) {
            list = path.list();
        } else {
            list = path.list(new FilenameFilter() {
                private Pattern pattern = Pattern.compile(args[0]);

                @Override
                public boolean accept(File dir, String name) {
                    return pattern.matcher(name).matches();
                }
            });
        }
        Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
        for (String dirItem : list) {
            System.out.println(dirItem);
        }
    }
}

2.目录实用工具

/**
 * @Author ZhangGJ
 * @Date 2020/12/04 08:13
 */
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) { // Overloaded
        return local(new File(path), regex);
    }

    // A two-tuple for returning a pair of objects:
    public static class TreeInfo implements Iterable<File> {
        public List<File> files = new ArrayList<File>();
        public List<File> dirs = new ArrayList<File>();

        // The default iterable element is the file list:
        @Override
        public Iterator<File> iterator() {
            return files.iterator();
        }

        void addAll(TreeInfo other) {
            files.addAll(other.files);
            dirs.addAll(other.dirs);
        }

        @Override
        public String toString() {
            return "dirs: " + PPrint.pformat(dirs) + "\n\nfiles: " + PPrint.pformat(files);
        }
    }

    public static TreeInfo walk(String start, String regex) { // Begin recursion
        return recurseDirs(new File(start), regex);
    }

    public static TreeInfo walk(File start, String regex) { // Overloaded
        return recurseDirs(start, regex);
    }

    public static TreeInfo walk(File start) { // Everything
        return recurseDirs(start, ".*");
    }

    public static TreeInfo walk(String start) {
        return recurseDirs(new File(start), ".*");
    }

    static TreeInfo recurseDirs(File startDir, String regex) {
        TreeInfo result = new TreeInfo();
        for (File item : startDir.listFiles()) {
            if (item.isDirectory()) {
                result.dirs.add(item);
                result.addAll(recurseDirs(item, regex));
            } else if (item.getName().matches(regex)) {
                result.files.add(item);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println(walk("."));
        } else {
            for (String arg : args) {
                System.out.println(walk(arg));
            }
        }
    }
}

3.目录的检查以及创建

  File类不仅仅只代表存在的文件或目录,也可以用File对象来创建新的目录或者不存在的整个目录路径,我们还可以查看文件的特性(如:大小,最后修改日期,读/写),检查某个File对象代表的是一个文件还是一个目录,并且可以删除文件。

二、输入和输出

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

1.InputStream

InputStream的作用是用来表示那些从不同数据源产生输入的类。

表1 InputStream类型
功能构造器如何使用
ByteArrayInputStream允许将内存的缓冲区当作InputStream使用缓冲区,字节将从中取出作为一种数据源:将其与FilterInputStream对象相连以提供有用接口
StringBufferInputStreamString转换成InputStream字符串,底层实现实际使用StringBuffer作为一种数据源:将其与FilterInputStream对象相连以提供有用接口
FileInputStream用于从文件中读取信息字符串,表示文件名、文件或FileDescriptor对象作为一种数据源:将其与FilterInputStream对象相连以提供有用接口
PipedInputStream产生用于写入相关PipedOutputStream的数据源,实现“管道化”概念PipedOutputStream作为多线程中数据源:将其与FilterInputStream对象相连以提供有用接口
SequenceInputStream将两个或多个InputStream对象转换成单一InputStream两个InputStream对象或一个容纳InputStream对象的集合Enumeration作为一种数据源:将其与FilterInputStream对象相连以提供有用接口
FilterInputStream抽象类,作为“装饰器”的接口,其中,“装饰器”为其他的InputStream类提供有用功能见表2见表2
表2 FilterInputStream类型
功能构造器如何使用
DataInputStreamDataOutputStream搭配使用,因此我们可以按照可移植方式从流读取基本数据类型InputStream包含用于读取基本类型数据的全部接口
BufferedInputStream使用它可以防止每次读取时都得尽兴实际写操作。代表“使用缓冲区”InputStream,可以指定缓冲区大小(可选的)本质上不提供接口,只不过是向进程中添加缓冲区所必需的。与接口对象搭配
LineNumberInputStream跟踪输入流中的行号,可调用getLineNumber()setLineNumber(int)InputStream仅增加了行号,因此可能要与接口对象搭配使用
PushbackInputStream具有“能弹出一个字节的缓冲区”。因此可以将读到的最后一个字符退回InputStream通常作为编译器的扫描器,之所以包含在内是因为Java编译器的需要,我们可能永远不会用到

2.OutputStream

表3 OutputStream类型
功能构造器如何使用
ByteArrayOutputStream在内存中创建缓冲区,所有送往“流”的数据都要放置在次缓冲区缓冲区初始化尺寸(可选的)用于指定数据的目的地:将其与FilterOutputStream对象相连以提供有用接口
FileOutputStream用于将信息写至文件字符串,表示文件名、文件或FileDescriptor对象指定数据的目的地:将其与FilterOutputStream对象相连以提供有用接口
PipedOutputStream任何写入其中的信息都会自动作为相关PipedInputStream的输出,实现“管道化”概念PipedInputStream指定用于多线程的数据的目的地:将其与FilterOutputStream对象相连以提供有用接口
FilterOutputStream抽象类,作为“装饰器”的接口,其中,“装饰器”为其他的OutputStream类提供有用功能见表4见表4
表4 FilterOutputStream类型
功能构造器如何使用
DataOutputStreamDataInputStream搭配使用,因此我们可以按照可移植方式向流中写入基本数据类型OutputStream包含用于写入基本类型数据的全部接口
PrintStream用于产生格式化输出。其中DataOutputStream处理数据的存储,PrintStream处理显示OutputStream,可以用boolean值指示是否在每次转换时晴空缓冲区(可选的)应该是对OutputStream对象的“final”封装可能会经常使用它
BufferedOutputStream使用它避免每次发送数据时都要进行实际的写操作。代表“使用缓冲区”。可以调用flush()清空缓冲区OutputStream可以指定缓冲区大小(可选的)本质上并不提供接口,只不过是向进程中添加缓冲区所必需的。与接口对象搭配

三、Reader和Writer

  当我们首次看见ReaderWriter时,可能会以为这是两个用来替代InputStreamOutputStream的类,但实际上并非如此,InputStreamOutputStream面向字节,而ReaderWriter面向字符。
  有时我们必须把来自与“字节“层次结构中的类和”字符”层次结构中的类结合起来使用,为了实现这个目的,要用到“适配器”类:InputStreamReader可以把InputStream转换成Reader,而OutputStreamWriter可以把OutputStream转换成Writer。设计ReaderWriter层次结构主要是为了国际化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值