NIO——FileDescriptor

本文详细介绍了FileDescriptor类的作用,它是特定结构的不透明句柄,用于表示打开的文件、套接字等字节源宿。文章解释了如何利用FileDescriptor创建FileInputStream或FileOutputStream,并探讨了其在MappedByteBuffer和DirectByteBuffer中的应用,以及sync方法如何确保数据同步到物理介质。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FileDescriptor 类

  1. 该类的作用?
    它用作特定结构的不透明句柄,这些结构表示打开的文件、打开的套接字或其它字节源宿。它实际用途是创建一个 FileInputStream 或 FileOutputStream,应用程序不应该创建自己的文件描述符
  2. 在哪里被用到了?
    MappedByteBuffer 中被用到, DirectByteBuffer 中又继承了 MappedByteBuffer, DirectByteBuffer 又是 NIO 的一个重要类,所以看看还是对我们理解底层有所帮助的
  3. 输出信息到屏幕示例代码:
	@Test
	void test() throws IOException {
		FileOutputStream out = new FileOutputStream(java.io.FileDescriptor.out);
		out.write("我会嘤嘤嘤!!!".getBytes());
		out.close();
	}
  1. standardStream(int fd) 方法
参数 fd代表含义
0标准输入流的句柄
1标准输出流的句柄
2标准错误流的句柄
  1. sync() 方法,这是一个本地(native)方法
    强制所有系统缓冲区与底层设备同步,该方法再将此 FileDescriptor 的所有修改数据和属性都写入相关设备返回。特别地,如果该 FileDescriptor 引用诸如文件系统中的文件的物理存储介质,同步将不会返回,直到与该 FileDescriptor 相关联的所有内存修改的副本已被写入物理介质。同步意图由需要物理存储(如文件)的代码用于已知状态,例如:提供简单事务的类可能会使用 sync 来确保由给定的文件引起的对文件的所有更改交易记录在存储介质上。sync 只影响此 FileDescriptor 下游的缓冲区。如果应用程序正在执行任何内存缓冲(例如,通过 BufferedOutputStream 对象 ),那么这些缓冲区必须在数据受同步影响之前刷新到 FileDescriptor 中(例如调用 OutputStream.flush)

	/**
     * Attach a Closeable to this FD for tracking.
     * parent reference is added to otherParents when
     * needed to make closeAll simpler.
     */
     // 在此FD上附加一个壁橱以进行跟踪。 需要使closeAll更简单时,将父引用添加到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);
        }
    }
### Java NIO 文件操作概述 Java NIO 提供了一套新的输入/输出功能,旨在改进传统 `java.io` 包中的类。NIO 的设计目标之一是提供更高效的文件处理能力[^1]。 #### 使用 Path 和 Files 类进行基本文件操作 为了更好地理解如何使用 Java NIO 进行文件操作,下面是一个简单的例子展示如何创建、读取和写入文件: ```java import java.nio.file.*; import java.io.IOException; public class FileOperations { public static void main(String[] args) throws IOException { // 创建路径对象 Path path = Paths.get("example.txt"); // 如果不存在则创建新文件 if (!Files.exists(path)) { Files.createFile(path); } // 向文件中写入字符串 String content = "Hello, world!"; Files.write(path, content.getBytes()); // 从文件中读取内容并打印到控制台 byte[] readContent = Files.readAllBytes(path); System.out.println(new String(readContent)); } } ``` 此代码片段展示了通过 `Path` 和 `Files` API 来执行常见的文件操作方法。这些API提供了更加灵活的方式来进行文件系统的访问以及数据传输的操作[^2]。 #### 处理目录遍历与监控事件 除了基础的文件读写外,Java NIO还支持复杂的场景比如监视特定位置的变化情况。这里有一个利用 `WatchService` 接口来监听指定目录下发生的更改的例子: ```java import java.nio.file.*; import java.util.List; import static java.nio.file.StandardWatchEventKinds.*; class WatchDir { private final WatchService watcher; private final Path dir; @SuppressWarnings("unchecked") public WatchDir(Path dir) throws IOException { this.watcher = FileSystems.getDefault().newWatchService(); this.dir = dir; register(dir); while (true) { WatchKey key; try { key = watcher.take(); // 阻塞直到有事件发生 } catch (InterruptedException e) { return; } List<WatchEvent<?>> events = key.pollEvents(); for (WatchEvent<?> event : events) { Kind<?> kind = event.kind(); if (kind == OVERFLOW) continue; WatchEvent<Path> ev = (WatchEvent<Path>)event; Path name = ev.context(); Path child = dir.resolve(name); System.out.format("%s: %s\n", event.kind().name(), child); if (kind.equals(ENTRY_CREATE)) register(child); } boolean valid = key.reset(); if (!valid) break; } } private void register(Path dir) throws IOException { WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); } } ``` 这段程序会持续运行,并报告任何发生在给定目录内的新增加、删除或修改过的项目的信息。注意,在注册子目录时也应用相同的逻辑以实现递归式的监测[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值