java filedescriptor_java IO笔记(FileDescriptor)

由于在看io源码中偶尔看到FileDescriptor,所以本篇决定讲讲FileDescriptor,从字面上来看它就是文件描述符。

官方是这么描述的:

8b5b602a9ca6db2e8462896170005627.png

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

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

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

5b0d5117fc5f09b6cd6d56181bd8e6ef.png

当时没有细说,本篇则来探索一下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 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();

}

}

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

6519c78aaa8ff4cee6fe3ff450bfcd84.png

第一句是一个使用了FileDescriptor.out创建的一个输出流打印出来,第二句为System.out打印出来的,两个流都是在控制台输出,再次证实了Sytem的in,out,err是通过FileDescriptor中的in,out,err来实现的。

然后我们看到对同一文件建立的两个不同的流,其fd值是不同的。

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

以上为本篇的内容。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值