Pee*_*ger 17 java file-io freebsd
我需要从Java访问编号的文件描述符 - 除了0,1或2.
如何才能做到这一点?我查看了FileDescriptor类,但没有找到任何方法用给定的文件描述符编号初始化它.
作为一个具体的例子,假设Java被另一个编程语言作为子进程调用.文件描述符3和4由另一种语言提供,用于输入和输出.
我需要的是Java InputStream和OutputStream连接到这些文件描述符的对象,就像System.in,System.out和System.error连接到文件解析器0,1和2一样.
我正在使用Java 1.6,这应该在类似Unix的系统上运行.
经过测试的工作方案:
文件描述符特殊文件系统条目的答案确实指向了以下可行的解决方案:
找出你的Unix系统是否以及在哪里有一个包含所有文件描述符的命名条目的特殊文件系统.
确保已安装此文件系统
FreeBSD的:把fdescfs /dev/fd fdescfs rw 0 0在/etc/fstab
或者mount -t fdescfs null /dev/fd在shell提示符下运行(可能带有sudo)
使用new FileInputStream("/dev/fd/3")并new FileOutputStream("/dev/fd/4")获取连接到filedescriptors的流(路径适用于FreeBSD,替换为您的操作系统路径)
Adr*_*onk 15
我很确定使用纯Java无法做到这一点 - 您可能必须使用本机代码将文件描述符绑定到FileDescriptor对象或FileInputStream或FileOutputStream对象.
编辑
如果您使用的是Linux,*BSD或macOS,则可以使用伪文件/ dev/fd/nnn来访问文件描述符nnn.
小智 10
使用SUN JavaVM,您可以:
FileDescriptor fd = new FileDescriptor();
sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess().set(fd,3);
FileInputStream fin = new FileInputStream(fd);
Run Code Online (Sandbox Code Playgroud)
我最近需要为在监狱中运行的Java子进程执行此操作.这意味着它无法访问/ dev/fd文件系统.
@Bozho评论说,反射可能会或可能不会创建FileDescriptor对象.不过,它似乎在我做过的简单测试中起作用.以下是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());
}
}
Run Code Online (Sandbox Code Playgroud)
为了测试这个,我制作了一个简单的Bash脚本来编译它,设置fd3,然后运行java程序:
#!/bin/bash
javac TestFD.java
exec 3>&1 # open fd3, redirect to stdout
java TestFD
exec 3>&-
Run Code Online (Sandbox Code Playgroud)
果然,fd3被重定向到stdout,并在终端输出"hi there \n".注释掉"exec 3>&1"行,Java程序按预期失败,并显示"未配置设备"IOException.
对于私有FileDescriptor构造函数的反射似乎在无法访问/ dev/fd的情况下工作正常,并且比尝试使用JNI创建FileDescriptor更不笨,这是我在其他地方看到的一个建议.
注意:我在BSD系统上测试了这个.它可能适用于其他系统,也可能不适用.