美文网首页
2020-03-22-Java的I/O系统

2020-03-22-Java的I/O系统

作者: 耿望 | 来源:发表于2020-03-24 11:14 被阅读0次

File

java提供了FIle类,用来访问某个文件或者目录。比如下面的例子可以用来遍历当前目录下的所有文件夹。

        String currentPath = System.getProperty("user.dir");
        System.out.println(currentPath);
        File file = new File(currentPath);
        List<String> list = Arrays.asList(file.list(new FilenameFilter() {
            
            @Override
            public boolean accept(File dir, String name) {
                return dir.isDirectory();
            }
        }));
        list.forEach(f -> System.out.println(f));

FileDescriptor

这个类实际上是封装了文件句柄或者文件描述符,开发者打开一个文件的时候,就持有了一个文件描述符。以FileOutputStream为例,看一下它的构造函数,注释1处,通过文件描述符,将OutputStream跟FIle建立了连接。

    public FileOutputStream(File file, boolean append)
        throws FileNotFoundException
    {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        this.fd = new FileDescriptor();
        fd.attach(this);//1
        this.append = append;
        this.path = name;

        open(name, append);
    }

I/O流

不管是输入还是输出,java提供了一种“流”的机制,因为发送端对象和接收端对象是千变万化的,java需要统一提供一个接口,而屏蔽具体的实现细节,这就是InputStream和OutputStream。
这里使用了一种装饰者模式,根据不同的需求,开发者可以使用不同类型的IOStream,比如FileOutputStream和ObjectOutputStream都继承了OutputStream,它们分别针对不同的发送端对象。
上面讲到了每个FileOutputStream,会通过文件描述符,跟文件建立联系,所以我们在使用Stream的时候就需要关注close方法,如果没有主动调用close,可能会出现内存泄漏或者文件句柄异常。

    public void close() throws IOException {
        synchronized (closeLock) {
            if (closed) {
                return;
            }
            closed = true;
        }

        if (channel != null) {
            channel.close();
        }

        fd.closeAll(new Closeable() {
            public void close() throws IOException {
               close0();
           }
        });
    }

虽然finalize方法会主动调用close,但是finalize要依赖JVM的主动gc,是不能保证一定会调用的。

    protected void finalize() throws IOException {
        if (fd != null) {
            if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
                flush();
            } else {
                /* if fd is shared, the references in FileDescriptor
                 * will ensure that finalizer is only called when
                 * safe to do so. All references using the fd have
                 * become unreachable. We can call close()
                 */
                close();
            }
        }
    }

实际上,IOStream根据传输数据的格式,有character类型和byte类型。
比如FileWriter,FileReader是char[]数组类型的,而FileOutputStream和FileInputStream是byte[]数组类型的。

相关文章

网友评论

      本文标题:2020-03-22-Java的I/O系统

      本文链接:https://www.haomeiwen.com/subject/slumyhtx.html