【问题标题】:PipedInputStream is not being read by internally called Java programPipedInputStream 未被内部调用的 Java 程序读取
【发布时间】:2013-07-27 11:56:08
【问题描述】:

我正在编写一个程序,该程序通过使用 Class 和 Method 类来调用 main 方法来执行另一个 Java 程序。这个其他程序然后尝试从 System.in 中读取。为了将参数传递给程序,我将 System.in 设置为连接到 PipedOutputStream 的 PipedInputStream。我将其他程序请求的参数传递给 PipedOutputStream,然后调用 main 方法。
但是,一旦调用该方法,程序就会死锁。这是为什么?从理论上讲,其他程序应该可以访问这些参数,因为它们已经在 PipedInputStream 中可用。
我无法改变其他程序读取输入的方式,所以这个解决方案行不通。

这里有一些示例代码:
我分配 PipedStreams 的部分

PipedInputStream inputStream = new PipedInputStream();
PipedStringOutputStream stringStream = new PipedStringOutputStream(); // custom class

try {
    stringStream.connect(inputStream);
} catch (IOException e2) {
    e2.printStackTrace();
}
System.setIn(inputStream);

我调用方法的部分:

Class main = classes.get(className);
try {
    Method m = main.getMethod("main", String[].class);

    // write all parameters to System.in
    String[] params = getParams(); // custom method, works (params is not empty)
    for(int j = 0; j < params.length; j++) {
       stringStream.write(params[j]);
    }

    params = null;
    m.invoke(null, (Object) params); // this is were the program stops
} catch(Exception e) {}

PipedStringOutputStream 类:

public class PipedStringOutputStream extends PipedOutputStream {

    public void write(String output) throws IOException {
        this.write((output + "\n").getBytes());
        flush();
    }
}

我从 System.in 读取的测试程序:

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    while(sc.hasNext()) {
        System.out.println(sc.nextLine());
    }
}

那么问题是什么?我必须在线程中启动 Streams 吗?为什么其他程序不从 PipedInputStream 读取输入?

【问题讨论】:

  • (1) 这里没有可以读取任何内容的代码,更不用说管道了。 (2) 由于您已经将参数直接传递给 main(),为什么要使用管道? (3) 这里的问题是什么?
  • 你的主要方法是做什么的?也显示它的代码。
  • @EJP: 1) 我添加了一些从 System.in 读取的示例代码 2) 我没有将参数直接传递给 main(),此时 params 为空。另一个程序从 System.in 中读取,所以我必须以这种方式传递参数。 3)问题是我如何将参数传递给 System.in 以便其他程序可以读取它们。假设管道是正确的步骤,我想知道我的代码有什么问题。

标签: java stream


【解决方案1】:

PipedInputStream 的 javadoc 明确表示:

通常,数据由一个线程从 PipedInputStream 对象读取,数据由其他线程写入相应的 PipedOutputStream。 不建议尝试在一个线程中同时使用这两个对象,因为这可能会使线程死锁

(强调我的)

使用ByteArrayOutputStream 将您的输入写入字节数组。然后从这个字节数组构造一个ByteArrayInputStream,并将System.in设置为这个ByteArrayInputStream

【讨论】:

  • 谢谢!如果我将其他程序的 main 方法作为普通方法调用调用,这工作正常,但是当我通过 invoke() 调用它时,它似乎无法从 ByteArrayInputStream 中读取,即使有正确的字节要读取. Scanner 的 hasNext() 方法总是返回 false。为什么会这样?
  • 直接调用使用反射的方法不应该改变任何东西。使用 hashNextLine() 来测试是否有下一行。没有 hasNext()。
  • 现在可以了。我对 Java 的按值调用系统有点挣扎,这就是为什么 System.in 没有设置为正确的流。
猜你喜欢
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多