2011-01-30 20 views
16

necesito para acceder a los descriptores de archivos numerados desde Java - distinto de 0, 1 ó 2.El uso de un descriptor de archivo numerado desde Java

¿Cómo puede hacerse esto? Miré la clase FileDescriptor pero no encontré ninguna forma de inicializarla con un número de descriptor de archivo dado.

Como ejemplo concreto, supongamos que se llama a Java como un proceso secundario desde otro lenguaje de programación. Los descriptores de archivos 3 y 4 son proporcionados por el otro idioma para entrada y salida.

Lo que necesito en Java son InputStream y OutputStream objetos conectados a estos archivos descriptores, al igual que System.in, System.out y System.error están conectados a presentar-desctiptors 0, 1 y 2.

Estoy usando Java 1.6 y esto debería funcionar en sistemas similares a Unix.

Probado solución de trabajo:

La respuesta a las entradas del sistema de archivos especiales de descriptor de archivo me hizo apuntar a la siguiente solución viable:

  1. averiguar si y donde el sistema por igual Unix tiene una sistema de archivos especial que contiene entradas con nombre para todos los descriptores de archivos.

    • Estoy usando FreeBSD donde fdescfs(5) es un sistema de archivos que hace justamente esto. Bajo Linux sería procfs.
  2. asegurarse de que este sistema de archivos está montado

    • FreeBSD: poner fdescfs /dev/fd fdescfs rw 0 0 en /etc/fstab

      o correr mount -t fdescfs null /dev/fd en un intérprete de comandos (probablemente con sudo)

  3. Use los nuevos FileInputStream("/dev/fd/3") y new FileOutputStream("/dev/fd/4") Para obtener los flujos conectados a los filedescriptors (los caminos son para FreeBSD, reemplace con sus caminos sistemas operativos)

+1

http://www.kfu.com/~nsayer/Java/jni-filedesc.html Podría ayudar –

Respuesta

13

Estoy bastante seguro de que esto no se puede hacer utilizando Java puro - probablemente tiene que usar código nativo para vincular un descriptor de archivo a un objeto FileDescriptor o un objeto FileInputStream o FileOutputStream.

EDITAR
Si está utilizando Linux, * BSD o MacOS, puede usar los archivos de pseudo/dev/fd/nnn nnn acceso al archivo descriptor.

+1

Sí, al aprender de sus respuestas que esto no es posible en Java en sí (que no soñé) Estaba buscando ayuda para el sistema operativo. Me estoy ejecutando bajo FreeBSD y tengo/dev/fd/ para todos los descriptores de archivos abiertos. –

2

Para empezar:

Las aplicaciones no deben crear sus propios descriptores de fichero

Puede tratar utilizando la reflexión para invocar el constructor private FileDescriptor(int fd), obteniendo el constructor y llamando setAccessible(true) en él . Pero eso es un truco y no puedo garantizar que funcione (es probable que no lo haga). Especialmente teniendo en cuenta la cita con la que comencé.

+2

Mi problema es que estos descriptores de archivos que obtengo son un dato dado por el tiempo de ejecución del otro idioma y otras restricciones externas en las que no tengo influencia. Por lo tanto, la necesidad de esto no es por mi elección. Probaré tu sugerencia para el truco. –

+0

Como sospechabas ... no funcionará. Solo puedo obtener constructores públicos a través de Class.getConstructor –

+1

@Peer Stritzinger - use 'FileDescriptor.getDeclaredConstructor (..)' – Bozho

8

con un sol JavaVM que puede hacer:

FileDescriptor fd = new FileDescriptor(); 
sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess().set(fd,3); 
FileInputStream fin = new FileInputStream(fd); 
+1

Esto no es compatible, no API y se romperá con Java 9. –

4

recientemente que tenía que hacer esto por un proceso hijo Java que se ejecuta en una cárcel. Esto significaba que no tenía acceso al sistema de archivos/dev/fd.

@Bozho hizo un comentario de que la reflexión puede o no funcionar para crear un objeto FileDescriptor. Sin embargo, parece funcionar en una simple prueba que hice. El siguiente es fuente de TestFD.java:

import java.lang.reflect.Constructor; 
import java.io.FileDescriptor; 
import java.io.FileOutputStream; 

public class TestFD { 
    public static void main(String[] args) throws Exception { 
    Constructor<FileDescriptor> ctor = FileDescriptor.class.getDeclaredConstructor(Integer.TYPE); 
    ctor.setAccessible(true); 
    FileDescriptor fd = ctor.newInstance(3); 
    ctor.setAccessible(false); 

    new FileOutputStream(fd).write("hi there\n".getBytes()); 
    } 
} 

Para probar esto, he hecho un script bash simple que lo compila, establece FD3, y se ejecuta el programa Java:

#!/bin/bash 

javac TestFD.java 

exec 3>&1 # open fd3, redirect to stdout 
java TestFD 
exec 3>&- 

Efectivamente, fd3 se redirige a stdout, y muestra "hola allí \ n" en la terminal. Comente la línea "exec 3> & 1" y el programa Java falla como se esperaba con una IOException "Dispositivo no configurado".

La reflexión sobre el constructor privado FileDescriptor parece funcionar bien en casos donde el acceso a/dev/fd no es posible, y es menos torpe que tratar de crear un FileDescriptor usando JNI, una sugerencia que he visto en otro lugar.

Nota: He probado esto en un sistema BSD. Puede o no funcionar en otros sistemas.

+0

Esto no funciona en Windows, ya que el único constructor es el predeterminado. – Vulcan

Cuestiones relacionadas