En Java, la clase FileDescriptor actúa como un identificador opaco para recursos como archivos abiertos, sockets u otros recursos de entrada/salida. Aunque representa internamente estos recursos, no permite operaciones directas; en cambio, se utiliza para crear flujos de E/S asociados que sí ofrecen métodos para leer o escribir datos.
El sistema define tres descriptores estándar:
in: representa la entrada estándar, típicamente el teclado.out: representa la salida estándar, usualmente la pantalla.err: representa la salida de error estándar, que también se muestra en la pantalla.
Para ilustrar el uso de out, consideremos que se puede crear un FileOutputStream vinculado a este descriptor para escribir en la consola. Por ejemplo:
public class EjemploConsola {
public static void main(String[] args) throws Exception {
try (java.io.FileOutputStream flujoConsola = new java.io.FileOutputStream(java.io.FileDescriptor.out)) {
flujoConsola.write("¡Salida desde FileDescriptor!".getBytes());
}
}
}
Este código produce el mismo efecto que System.out.println("¡Salida desde FileDescriptor!");, ya que Java encapsula esta funcionalidad en la clase System para mayor conveniencia.
A continuación, se presentan ejemplos que demuestran operaciones con archivos usando FileDescriptor. En el primer caso, se escribe en la consola y en un archivo simultáneamente:
public class EjemploArchivo {
private static final String RUTA_ARCHIVO = "datos/prueba.txt";
private static final String TEXTO = "Contenido de ejemplo";
public static void main(String[] args) throws Exception {
escribirEnConsolaYArchivo();
leerDesdeArchivo();
}
// Equivale a usar System.out.println, pero mediante FileDescriptor
private static void escribirEnConsolaYArchivo() throws Exception {
try (java.io.PrintStream ps = new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out))) {
ps.println(TEXTO);
}
}
// Escritura y lectura de archivo usando descriptores
private static void escribirEnArchivo() throws Exception {
try (java.io.FileOutputStream fs = new java.io.FileOutputStream(RUTA_ARCHIVO)) {
java.io.FileDescriptor fd = fs.getFD();
try (java.io.FileOutputStream fsOtro = new java.io.FileOutputStream(fd)) {
fs.write("Primera línea".getBytes());
fsOtro.write("Segunda línea".getBytes());
}
}
}
private static void leerDesdeArchivo() throws Exception {
try (java.io.FileInputStream fs1 = new java.io.FileInputStream(RUTA_ARCHIVO)) {
java.io.FileDescriptor fd = fs1.getFD();
try (java.io.FileInputStream fs2 = new java.io.FileInputStream(fd)) {
System.out.println("Lectura1: " + (char) fs1.read());
System.out.println("Lectura2: " + (char) fs2.read());
}
}
}
}
En estos ejemplos, los descriptores de archivo permiten múltiples referencias al mismo recurso subyacente, facilitando operaciones concurrentes o compartidas. Es importante cerrar adecuadamente los flujos para liberar recursos del sistema.