Java无法构造描述符,Java IO流之文件描述符FileDescriptor

简介

POSIX标准

先了解一下POSIX标准,POSIX标准是操作系统为应用程序提供的接口,是电子和电气工程协会(简称IEEE)为要在各种UNIX操作系统上运行软件而定义的一系列API标准总称,目的是为了保证应用程序的可移植性.也就是说为一个POSIX操作系统编写的应用程序,在另外一个POSIX操作系统里面依旧可以运行.比如:POSIX标准接口:Open()打开文件,create()创建文件,read()读取文件,write()写入文件等接口,如果在以POSIX标准的操作系统编写的应用程序调用到了Open()接口(操作系统提供接口),那么应用程序移植到别的以POSIX标准的操作系统,同样也可以运行.因为调用操作系统接口都是一样的.都是Open().

文件描述符

对内核而言,所有打开的文件(或者socket)都是由文件描述符引用,打开一个现存的文件或者是创建一个新文件时,内核会向当前进程返回一个文件描述符,那么根据文件描述符就可以找到对应的文件。比如读写一个文件的简单步骤:

应用程序调用POSIX标准操作系统接口open()或者create(),方法将会返回文件描述符来标识该文件,

将文件描述符的值传递给应用程序中的read()或者write().文件描述符的值结合流就可以读取数据或者写入数据到文件中。

文件描述符是一个非负的整数,在POSIX标准的应用程序中,整数0,1,2分别表示的是标准输入,标准输出,标准错误输出的描述符.最早期的UNIX版本中最大值是19(也就是容许每个进程打开20个文件),现在系统都有所增加,比如Linux是1024,在java中虽然设计使用的是抽象度更高的流,但是依然需要文件描述符与操作系统进行交互.

FileDescriptor介绍

在java中FileDescriptor表示的是"文件描述符",对于文件描述符中0,1,2分别表示如下:

整数值

名称

0

标准输入描述符

1

标准输出描述符

2

标准错误输出描述符

对于三个"文件描述符",用法基本上是相似的.比如标准输出描述符,看FileDescriptor源码,调用的方式是FileDescriptor.out.但是由于FileDescriptor没有直接输出屏幕的接口,需要借助输出流对象,通过调用输出流的方法write()方法,可以将对应的字符输出到控制台上,案例如下:

public class FileDescriptorDemo {

public static void main(String[] args) throws Exception {

FileOutputStream fos = new FileOutputStream(FileDescriptor.out);

fos.write("abcd".getBytes());

fos.close();

}

}

运行的结果是:

abcd

当然在java中已经有相应封装的接口,可以直接输出到控制台:System.out.println("abcd").其余标准输入描述符对应是System.in,而标准错误输出对应的是System.err.

源码分析

public final class FileDescriptor {

//打开的文件或者socket时,简单说操作系统会返回一个fd值,通过该值可以对文件,socket等进行相关操作,

private int fd;

//关联的流只有一个,则保存到parent中

private Closeable parent;

//关联的流很多,则保存到集合otherParents中

private ListotherParents;

//用于判断是否释放文件文件引用

private boolean closed;

//无参数构造方法,fd赋值为-1, 由于java中文件描述符是大于0的整数,所以无意义.

public FileDescriptor() {

fd = -1;

}

//有参构造方法,由于修饰符是private,无法设置fd

private FileDescriptor(int fd) {

this.fd = fd;

}

//标准的输入,文件描述符用0表示

public static final FileDescriptor in = new FileDescriptor(0);

//标准的输出,文件描述符用1表示

public static final FileDescriptor out = new FileDescriptor(1);

//标准错误输出,文件描述符用2表示

public static final FileDescriptor err = new FileDescriptor(2);

//判断是否有效,非-1有效.所以无参构造方法中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集合中.

//结合下面closeAll()方法,释放文件描述符的引用,同时也会将对应所有的流关闭

//因为文件描述符释放的情况下,流的存在也无意义

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);

}

}

//关闭所有与文件描述符关联的所有的流对象

@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;

}

}

}

}

总结:

1.文件描述符就是打开文件或socket时,操作系统返回的一个int类型值.会根据文件描述符结合流操作对应的文件或者socket.

2.文件描述符是一个非负的整数,其中0,1,2分别表示的标准输入,标准输出和标准错误输出.在java中已经有相关接口封装,分别是System.in;System.out;System.err.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值