我正在打开一个 PowerShell 实例并通过 System.in 向它发送命令,我想将输出收集到一个队列中,这样我就可以在不干扰输入命令的情况下打印结果。但是,队列没有在主线程上填充,并且在主线程上休眠只是稍微解决了这个问题。我想问题在于不同步队列,但我不确定如何。
package PWST;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class PWST {
public static void main(String[] args) {
try {
Scanner in = new Scanner(System.in);
System.out.print("\033[H\033[2J > "); // clear console.
String[] tokens = in.nextLine().split(",");
Queue<String> stdout = new LinkedList<>();
Queue<String> stderr = new LinkedList<>();
Process process = Runtime.getRuntime().exec("powershell.exe");
new Thread(new SPQ(process.getInputStream(), stdout)).start();
new Thread(new SPQ(process.getErrorStream(), stderr)).start();
PrintWriter out = new PrintWriter(process.getOutputStream());
for (String token : tokens) // parse commands (will be expanded to continuously ask for input)
out.println(token.strip());
// print powershell output after:
System.out.println(stdout);
System.out.println(stderr);
in.close();
out.close();
process.waitFor();
System.out.println("Shell link closed");
} catch (Exception e) { e.printStackTrace(); }
}
}
package PWST;
import java.io.InputStream;
import java.util.Queue;
class SPQ implements Runnable {
private Queue<String> queue;
private InputStream istrm;
public SPQ(InputStream istrm, Queue<String> queue) {
this.istrm = istrm;
this.queue = queue;
}
public void run() {
try {
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm.read(buffer)) != -1; )
queue.add(new String(buffer, 0, length)); // store output in queue
} catch (Exception e) { e.printStackTrace(); }
}
}
至少有两个问题。
首先,关闭Scanner
andPrintWriter
也将关闭它们的不死流(在这种情况下Scanner
是从标准输入读取的)。这是不可取的,因为,首先,您永远不想关闭 stdin 流,其次,该过程可能尚未完成对流的处理,但更重要的是,我会非常小心关闭不是您自己创建的流,只是说.
第二个问题是,您试图在SPQ
实际有时间处理输出之前读取(流的)输出,例如,如果我调整您的代码并使用...
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Queue;
public final class Main {
public static void main(String[] args) throws IOException, InterruptedException {
new Main();
}
public Main() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("bash", "-c", "ls");
pb.redirectErrorStream(true);
System.out.println(">> Start process");
Process p = pb.start();
Queue<String> stdout = new LinkedList<>();
Thread thread = new Thread(new SPQ(p.getInputStream(), stdout));
System.out.println(">> Start thread");
thread.start();
System.out.println(">> Waiting for process to exit");
p.waitFor();
System.out.println("<< Process has exited");
System.out.println(stdout);
}
class SPQ implements Runnable {
private Queue<String> queue;
private InputStream istrm;
public SPQ(InputStream istrm, Queue<String> queue) {
this.istrm = istrm;
this.queue = queue;
}
public void run() {
System.out.println(">> Started reading stream");
try {
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm.read(buffer)) != -1;) {
queue.add(new String(buffer, 0, length)); // store output in queue
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("<< Done reading stream");
}
}
}
它会输出...
>> Start process
>> Start thread
>> Waiting for process to exit
<< Process has exited
>> Started reading stream
[]
<< Done reading stream
如您所见,我已经Queue
在线程完成处理流之前打印了内容。
如果我在打印thread.join();
后添加p.waitFor();
...
>> Start process
>> Start thread
>> Waiting for process to exit
>> Started reading stream
<< Done reading stream
<< Process has exited
[contents
of
my
working
directory
which
is
not
very
interesting]
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Queue;
public final class Main {
public static void main(String[] args) throws IOException, InterruptedException {
new Main();
}
public Main() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("bash", "-c", "ls");
pb.redirectErrorStream(true);
System.out.println(">> Start process");
Process p = pb.start();
Queue<String> stdout = new LinkedList<>();
Thread thread = new Thread(new SPQ(p.getInputStream(), stdout));
System.out.println(">> Start thread");
thread.start();
System.out.println(">> Waiting for process to exit");
p.waitFor();
thread.join();
System.out.println("<< Process has exited");
System.out.println(stdout);
}
class SPQ implements Runnable {
private Queue<String> queue;
private InputStream istrm;
public SPQ(InputStream istrm, Queue<String> queue) {
this.istrm = istrm;
this.queue = queue;
}
public void run() {
System.out.println(">> Started reading stream");
try {
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm.read(buffer)) != -1;) {
queue.add(new String(buffer, 0, length)); // store output in queue
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("<< Done reading stream");
}
}
}
请注意 - 我没有运行 Windows,所以我无法测试Powershell
并且我已经完成了我能想到的最小示例,所以我没有将内容写入流,但从概念上讲,这解决了你似乎是的问题有
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句