Java FileDescriptor 类
最后修改时间:2025 年 4 月 16 日
java.io.FileDescriptor 类表示一个打开的文件、套接字或其他 I/O 资源。它充当底层特定于机器的结构的句柄。FileDescriptor 实例通常由 I/O 流创建。
FileDescriptor 提供了对操作系统使用的本机文件描述符的访问。它包含三个标准流:in、out 和 err。这些分别对应于标准输入、输出和错误流。
FileDescriptor 类概述
FileDescriptor 是一个简单的类,只有几个方法。它的主要目的是提供对本机文件句柄的访问。该类在 Java 的 I/O 类中内部使用,很少由应用程序代码直接使用。
public final class FileDescriptor {
public static final FileDescriptor in;
public static final FileDescriptor out;
public static final FileDescriptor err;
public FileDescriptor();
public boolean valid();
public native void sync() throws SyncFailedException;
}
上面的代码显示了 FileDescriptor 的结构。该类包含三个用于标准流的静态描述符。sync 方法强制所有系统缓冲区与底层设备同步。
标准流 FileDescriptor
Java 为系统 I/O 提供了三个标准的 FileDescriptor 对象。 这些可以通过 System.in、System.out 和 System.err 访问。 它们分别代表标准输入、输出和错误流。
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class Main {
public static void main(String[] args) {
// Access standard stream FileDescriptors
FileDescriptor inFd = FileDescriptor.in;
FileDescriptor outFd = FileDescriptor.out;
FileDescriptor errFd = FileDescriptor.err;
System.out.println("Standard input valid: " + inFd.valid());
System.out.println("Standard output valid: " + outFd.valid());
System.out.println("Standard error valid: " + errFd.valid());
// Demonstrate using FileDescriptor with FileOutputStream
try (FileOutputStream fos = new FileOutputStream(outFd)) {
PrintStream ps = new PrintStream(fos);
ps.println("This goes to standard output via FileDescriptor");
} catch (Exception e) {
e.printStackTrace();
}
}
}
此示例演示了如何访问标准流 FileDescriptor。 valid 方法检查描述符是否打开。 我们还展示了如何将 FileDescriptor 与 FileOutputStream 一起使用以写入标准输出。 try-with-resources 确保正确的资源清理。
创建和验证 FileDescriptor
FileDescriptor 对象通常从 I/O 流获取,而不是直接创建。 valid 方法检查描述符是否仍然打开且有效。 这对于检查流状态很有用。
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
// Create FileInputStream and get its FileDescriptor
FileInputStream fis = new FileInputStream("test.txt");
FileDescriptor fd1 = fis.getFD();
System.out.println("Input FileDescriptor valid: " + fd1.valid());
// Create FileOutputStream and get its FileDescriptor
FileOutputStream fos = new FileOutputStream("output.txt");
FileDescriptor fd2 = fos.getFD();
System.out.println("Output FileDescriptor valid: " + fd2.valid());
// Close streams and check validity
fis.close();
fos.close();
System.out.println("After closing:");
System.out.println("Input FD valid: " + fd1.valid());
System.out.println("Output FD valid: " + fd2.valid());
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例显示了如何从流中获取 FileDescriptor 对象。 我们创建输入和输出流并获取它们的描述符。 关闭流后,我们检查描述符的有效性。 关闭的流会导致无效的描述符。
使用 sync() 将数据强制写入磁盘
sync 方法强制所有系统缓冲区将数据写入物理存储设备。 这确保数据实际上已写入磁盘而不是缓存。 如果操作失败,sync 会抛出 SyncFailedException。
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SyncFailedException;
public class Main {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("important.dat")) {
// Write critical data
fos.write("Critical system data".getBytes());
// Get FileDescriptor and sync
FileDescriptor fd = fos.getFD();
System.out.println("Before sync - valid: " + fd.valid());
try {
fd.sync(); // Force data to disk
System.out.println("Data successfully synced to disk");
} catch (SyncFailedException e) {
System.err.println("Failed to sync data: " + e.getMessage());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例演示了如何使用 sync 来确保将数据写入磁盘。 我们将关键数据写入文件,然后调用 sync。 如果设备无法同步,则操作可能会失败。 使用此方法时,始终处理 SyncFailedException。
比较 FileDescriptor
可以比较 FileDescriptor 对象以检查它们是否引用相同的底层系统资源。 这是使用标准对象比较完成的,因为 FileDescriptor 没有覆盖 equals。 只有对同一对象的引用才被认为是相等的。
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
// Create two input streams for the same file
FileInputStream fis1 = new FileInputStream("test.txt");
FileInputStream fis2 = new FileInputStream("test.txt");
FileDescriptor fd1 = fis1.getFD();
FileDescriptor fd2 = fis2.getFD();
FileDescriptor fd3 = fd1;
System.out.println("fd1 == fd2: " + (fd1 == fd2));
System.out.println("fd1 == fd3: " + (fd1 == fd3));
// Standard streams comparison
FileDescriptor stdOut1 = FileDescriptor.out;
FileDescriptor stdOut2 = FileDescriptor.out;
System.out.println("stdOut1 == stdOut2: " + (stdOut1 == stdOut2));
fis1.close();
fis2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例显示了 FileDescriptor 比较的工作方式。 同一文件的两个描述符是不同的对象。 标准流描述符是单例。 FileDescriptor 不提供基于内容的比较,仅提供引用相等性。
将 FileDescriptor 与 RandomAccessFile 一起使用
RandomAccessFile 还可以提供对 FileDescriptor 对象的访问。 这允许对以随机访问模式打开的文件进行低级操作。 该描述符可以与来自其他 I/O 类的描述符类似地使用。
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Main {
public static void main(String[] args) {
try (RandomAccessFile raf = new RandomAccessFile("data.bin", "rw")) {
// Get FileDescriptor from RandomAccessFile
FileDescriptor fd = raf.getFD();
System.out.println("RandomAccessFile descriptor valid: " + fd.valid());
// Perform operations
raf.writeInt(42);
raf.writeDouble(3.14159);
// Force data to disk
fd.sync();
System.out.println("Data written and synced");
// Verify descriptor remains valid
System.out.println("Descriptor still valid: " + fd.valid());
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例演示了如何将 FileDescriptor 与 RandomAccessFile 一起使用。 我们以读写模式打开一个文件并获取其描述符。 写入数据后,我们使用 sync 来确保将其写入磁盘。 描述符在整个操作过程中保持有效。
来源
在本文中,我们介绍了 Java FileDescriptor 类的基本方法和特性。 理解这些概念对于在 Java 应用程序中使用低级 I/O 操作至关重要。
作者
列出所有Java教程。