美文网首页
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