Java - 读取另一个线程正在写入 stdout/stderr 的内容 - 如何?
我有一个函数“a()”,它调用另一个写入标准输出的函数“b()”。我无法修改“b()”,但我希望能够读取“b”正在写入的内容并写回标准输出以供“b”读取,这意味着:
public void a() {
// start a thread that listens to stdout.
// the thread should print a name to stdout after "b" print "Please enter your name"
b();
}
public void b() { // I cannot modify this function
System.out.println("Welcome! The time is " + System.currentTimeMillis());
System.out.println("Please enter your name");
String name = ...
// ... b reads here the name that the thread from function a() will write
// ...
System.out.println("This is the name that was entered: " + name);
}
我想过在新进程中启动“b”,但我不确定如何,除非我将“b”包装在主函数中并使用命令行运行它 - 我很乐意提供建议。 如果它不是一个进程,我不知道如何实现将由“a()”激活的线程。
我尝试使用:
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = stdin.readLine()) != null) {
...
}
但它没有捕获“b”正在写的内容。
感谢您的帮助
I have a function "a()" that calls another function "b()" that writes to stdout. I cannot modify "b()", but I want to be able to read what "b" is writing and write back to stdout for "b" to read, meaning:
public void a() {
// start a thread that listens to stdout.
// the thread should print a name to stdout after "b" print "Please enter your name"
b();
}
public void b() { // I cannot modify this function
System.out.println("Welcome! The time is " + System.currentTimeMillis());
System.out.println("Please enter your name");
String name = ...
// ... b reads here the name that the thread from function a() will write
// ...
System.out.println("This is the name that was entered: " + name);
}
I thought about starting "b" in a new process but I wasn't sure how unless I wrap "b" in a main function and run it using a command line - I'd be happy for suggestions.
If it's not a process, I'm not sure how to implement the thread that will be activated by "a()".
I tried using:
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = stdin.readLine()) != null) {
...
}
but it doesn't catch what "b" is writing.
Thanks for the help
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以在另一个进程中运行 b(),但您不需要这样做。
System.out 是一个打印流。如果您仔细阅读 javadoc会注意到System.setOut方法。有了它,您可以用另一个 PrintStream 替换 System.out。
示例(未测试):
该解决方案存在线程不安全的问题。如果任何其他线程在“更改”时写入 System.out,则输出也将被重定向。为了摆脱这个问题,我认为您需要在另一个 JVM 上运行 b() 或使用 PrintStream 根据线程或上下文拆分(解复用)输出。
You can run b() in another process but you don't need to do so.
System.out is a PrintStream. If you read the javadoc carefully you will notice System.setOut method. With it you can replace System.out with another PrintStream.
Example (not tested):
This solution has the problem of not being thread safe. If any other thread write to System.out when it is 'changed' the output will get redirected too. To get rid of this problem I think you need to run b() on another JVM or use a PrintStream that split (deMux) the output depending on the thread or context.
不幸的是,在 Java 中没有简单的方法可以做到这一点。最大的问题是 System.out 和 System.in 是两个独立的文件,分别由 FileDescriptor.out 和 FileDescriptor.in 创建分别。它们没有以任何方式连接,因此您无法写入
System.out
并期望在System.in
中看到它。您的选择是:
以某种方式在外部进程中运行
b()
。是的,您需要将其放入具有main()
函数的类中,并进行大量复杂的进程设置,例如获取java.exe
的路径并进行设置好的部分是写入和读取进程将按照您的预期工作。创建两个自定义输入和输出流,可以将所有流量复制到另一个输入/输出流,并将其发送到
System.{in,out}
,并使用设置它们System.set{输入,输出}
。这样,您就可以监视这些流,而不会影响可能使用 System.{in,out} 的其他代码。作为 2 中提到的自定义
OutputStream
的示例,请尝试这样的操作:不幸的是,您将不得不对
System.in
重复上述过程,这意味着更疯狂的代码,但我不认为事情会比这更容易。如果您准备好进行一些非常疯狂的操作,也许您可以获取一些 java 库(最有可能使用本机代码),它可以为您提供当前运行的 JVM 的 Process 对象,然后使用
get{Input,Output}Stream()
方法来完成这项工作。Unfortunately there is not easy way of doing this in Java. The biggest problem is that
System.out
andSystem.in
are two separate files, created fromFileDescriptor.out
andFileDescriptor.in
respectively. They are not connected in any way, and therefore you can't write toSystem.out
and expect to see it inSystem.in
.Your options are:
Run
b()
in external process somehow. Yes, you'll need to put it in a class withmain()
function and do lots of complicated process setup, like getting the path tojava.exe
and setting up classpaths etc. The good part is that writing to and reading from the process will work as you expect.Create two custom Input and Output streams that can duplicate all traffic to another in/out stream, as well as sending it to
System.{in,out}
, and set them usingSystem.set{In,Out}
. This way you can monitor those streams without affecting other code that might by usingSystem.{in,out}
.As an example of the custom
OutputStream
mentioned in 2, try something like this:Unfortunately you will have to repeat the above process for
System.in
, which means more crazy code, but I don't think it will get easier than this.If you are ready for some really crazy action, maybe you can get hold of some java library (most likely with native code), that can give you the
Process
object of the currently running JVM, and then useget{Input,Output}Stream()
methods to do the job.如何使用 System.setOut 设置 System.out
How about setting System.out with System.setOut