美文网首页Java
Java IO笔记(FileDescriptor)

Java IO笔记(FileDescriptor)

作者: moonfish1994 | 来源:发表于2019-12-16 15:54 被阅读0次

(最近刚来到简书平台,以前在CSDN上写的一些东西,也在逐渐的移到这儿来,有些篇幅是很早的时候写下的,因此可能会看到一些内容杂乱的文章,对此深感抱歉,以下为正文)


正文

由于在看IO源码中偶尔会看到FileDescriptor,所以本篇决定讲讲FileDescriptor,从字面上来看它就是文件描述符。
官方是这么描述的:


描述

可以看出,FileDescriptor可以看做是一种指向文件引用的抽象化概念。它能表示一个开放文件,一个开放的socket或者一个字节的源。它最主要的用途就是去创建FileInputStream或者FileOutputStream。并且也说了不应该创建应用自己的文件描述符。

不得不说每次看这种官方的解释都表示云里雾里,毕竟与那些大神们差距太大,只能细细品味了。

不知道还是否记得前面讲述的System.out,System.in,System.error了,当时它们初始化的时候就用到了FileDescriptor:


FileDescriptor

当时没有细说,本篇则来探索一下FileDescriptor。

下面先贴上源码,通过源码来进行一定程度地学习:

package java.io;
 
import java.util.ArrayList;
import java.util.List;
 
public final class FileDescriptor {
    //封装了一个int型的值fd,每个打开的文件,socket等都会给你一个fd值,通过该值可以对文件,socket等进行相关操作,有点儿类似操作对象的索引
    private int fd;
    //
    private Closeable parent;
    //
    private List<Closeable> otherParents;
    //封装了一个boolean类型变量closed,用来判断fd是否被释放
    private boolean closed;
 
    //不带参构造,默认fd为-1,目测-1没什么意义,符合官方说的不建议直接创建自己的对象
    public /**/ FileDescriptor() {
        fd = -1;
    }
    //一个带参私有的构造方法,将fd值设为传入的参数
    private /* */ FileDescriptor(int fd) {
        this.fd = fd;
    }
 
    //定义的一个标准输入,fd值为0
    public static final FileDescriptor in = new FileDescriptor(0);
 
    //定义的一个标准输出,fd值为1
    public static final FileDescriptor out = new FileDescriptor(1);
 
    //定义的一个标准错误输出,fd值为2,我想在不同的环境下,标准流都能工作的原因应该就是因为已经在这里限定好了吧
    public static final FileDescriptor err = new FileDescriptor(2);
    
 
    //判断是否有效,这也证实了前面构造函数中fd赋值为-1是无效的
    public boolean valid() {
        return fd != -1;
    }
 
    public native void sync() throws SyncFailedException;
 
    /* This routine initializes JNI field offsets for the class */
    private static native void initIDs();
 
    static {
        initIDs();
    }
 
    // Set up JavaIOFileDescriptorAccess in SharedSecrets
    static {
        sun.misc.SharedSecrets.setJavaIOFileDescriptorAccess(
            new sun.misc.JavaIOFileDescriptorAccess() {
                public void set(FileDescriptor obj, int fd) {
                    obj.fd = fd;
                }
 
                public int get(FileDescriptor obj) {
                    return obj.fd;
                }
 
                public void setHandle(FileDescriptor obj, long handle) {
                    throw new UnsupportedOperationException();
                }
 
                public long getHandle(FileDescriptor obj) {
                    throw new UnsupportedOperationException();
                }
            }
        );
    }
 
    //像otherParents集合中添加元素
    synchronized void attach(Closeable c) {
        if (parent == null) {
            // first caller gets to do this
            parent = c;
        } else if (otherParents == null) {
            otherParents = new ArrayList<>();
            otherParents.add(parent);
            otherParents.add(c);
        } else {
            otherParents.add(c);
        }
    }
 
    //关闭otherParents所有的元素
    @SuppressWarnings("try")
    synchronized void closeAll(Closeable releaser) throws IOException {
        if (!closed) {
            closed = true;
            IOException ioe = null;
            try (Closeable c = releaser) {
                if (otherParents != null) {
                    for (Closeable referent : otherParents) {
                        try {
                            referent.close();
                        } catch(IOException x) {
                            if (ioe == null) {
                                ioe = x;
                            } else {
                                ioe.addSuppressed(x);
                            }
                        }
                    }
                }
            } catch(IOException ex) {
                /*
                 * 
                 */
                if (ioe != null)
                    ex.addSuppressed(ioe);
                ioe = ex;
            } finally {
                if (ioe != null)
                    throw ioe;
            }
        }
    }
}

因为笔者也是一个初学者,看了源码后,也没有发现什么,只是知道了下其中定义了3个标准分别为in,out,err,java中的标准流就是通过这里来实现的。其次就是fd的值不是我们可以随意修改的,是底层给我们的,我们可以通过该值取进行操作。并且FileDescriptor中需要进行close方法执行,应该是对文件等操作结束后,执行完close以后,才真正释放该索引以及对应的内存读写空间。
下面用1个小例子来展示一下FileDescriptor的使用及特性:

package test;
 
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Test4 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream(FileDescriptor.out);
        fos.write("FileDescriptor:这里证明了System.out,就是使用FileDescriptor.out来创建的\r".getBytes());
        System.out.println("System.out:控制台输出");
        FileOutputStream fos1 = new FileOutputStream("./src/file/test.txt");
        FileOutputStream fos2 = new FileOutputStream("./src/file/test.txt");
        System.out.println("fos1:"+fos1.getFD());
        System.out.println("fos2:"+fos2.getFD());
        fos.close();
        fos1.close();
        fos2.close();
    }
}

执行上述代码可以在控制台看到如下打印:


控制台输出

第一句是一个使用了FileDescriptor.out创建的一个输出流打印出来,第二句为System.out打印出来的,两个流都是在控制台输出,再次证实了Sytem的in,out,err是通过FileDescriptor中的in,out,err来实现的。
然后我们看到对同一文件建立的两个不同的流,其fd值是不同的。

最后总结一下,这个类我们好像不怎么能使用到,因为我们无法去定义其中的fd值,所以我们能使用的基本只有其中为我们定义好的in,out,err了,但是众所周知,java已将帮我们封装好了更方便的System.in/out/err了,所以平常我们基本见不到其使用,只有在看源码时,会经常碰到了。

以上为本篇的全部内容。

相关文章

  • Java IO笔记(FileDescriptor)

    (最近刚来到简书平台,以前在CSDN上写的一些东西,也在逐渐的移到这儿来,有些篇幅是很早的时候写下的,因此可能会看...

  • Java IO 流(二) File

    FileIO 在java.io包中主要有File、FileDescriptor、FileinputStream、F...

  • Java.io.FileDescriptor(io流二)

    FileDescriptor:文件描述符、 该结构表示开放文件、开放套接字或者字节的另一个源或接收者 文件描述符类...

  • java io

    参考Java IO学习笔记(一):File类Java IO学习笔记(二):RandomAccessFile类Jav...

  • JAVA IO基本知识

    本部分总结一下JAVA IO的相关知识。 全部章节传送门: JAVA IO学习笔记: IO基本知识 JAVA IO...

  • Java IO 笔记

    学习Java中的IO,首先要理解Java中IO的流模型。所谓流,可以假想成河流,流的数据源,就是河流的发源地,流是...

  • Java IO笔记(IO简述)

    (最近刚来到简书平台,以前在CSDN上写的一些东西,也在逐渐的移到这儿来,有些篇幅是很早的时候写下的,因此可能会看...

  • Java IO学习笔记总结

    Java IO学习笔记总结 前言 前面的八篇文章详细的讲述了Java IO的操作方法,文章列表如下基本的文件操作字...

  • Java的IO和NIO

    Java的IO和NIO 一、Java的IO Java的IO功能在java.io包下,包括输入、输出两种IO流,每种...

  • Netty 权威指南笔记(一):网络 I/O 模型和 Java

    Netty 权威指南笔记(一):网络 I/O 模型和 Java IO 入门 Java I/O 模型的实现离不开底层...

网友评论

    本文标题:Java IO笔记(FileDescriptor)

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