Stdout and stderr in java

How do I handle multiple streams in Java?

I’m trying to run a process and do stuff with its input, output and error streams. The obvious way to do this is to use something like select() , but the only thing I can find in Java that does that is Selector.select() , which takes a Channel . It doesn’t appear to be possible to get a Channel from an InputStream or OutputStream ( FileStream has a getChannel() method but that doesn’t help here) So, instead I wrote some code to poll all the streams:

while( !out_eof || !err_eof ) < while( out_str.available() ) < if( (bytes = out_str.read(buf)) != -1 ) < // Do something with output stream >else out_eof = true; > while( err_str.available() ) < if( (bytes = err_str.read(buf)) != -1 ) < // Do something with error stream >else err_eof = true; > sleep(100); > 

which works, except that it never terminates. When one of the streams reaches end of file, available() returns zero so read() isn’t called and we never get the -1 return that would indicate EOF. One solution would be a non-blocking way to detect EOF. I can’t see one in the docs anywhere. Alternatively is there a better way of doing what I want to do? I see this question here: link text and although it doesn’t exactly do what I want, I can probably use that idea, of spawning separate threads for each stream, for the particular problem I have now. But surely that isn’t the only way to do it? Surely there must be a way to read from multiple streams without using a thread for each?

Читайте также:  User login class in php

2 Answers 2

As you said, the solution outlined in this Answer is the traditional way of reading both stdout and stderr from a Process. A thread-per-stream is the way to go, even though it is slightly annoying.

You will indeed have to go the route of spawning a Thread for each stream you want to monitor. If your use case allows for combining both stdout and stderr of the process in question you need only one thread, otherwise two are needed.

It took me quite some time to get it right in one of our projects where I have to launch an external process, take its output and do something with it while at the same time looking for errors and process termination and also being able to terminate it when the java app’s user cancels the operation.

I created a rather simple class to encapsulate the watching part whose run() method looks something like this:

public void run() < BufferedReader tStreamReader = null; try < while (externalCommand == null && !shouldHalt) < logger.warning("ExtProcMonitor(" + (watchStdErr ? "err" : "out") + ") Sleeping until external command is found"); Thread.sleep(500); >if (externalCommand == null) < return; >tStreamReader = new BufferedReader(new InputStreamReader(watchStdErr ? externalCommand.getErrorStream() : externalCommand.getInputStream())); String tLine; while ((tLine = tStreamReader.readLine()) != null) < logger.severe(tLine); if (filter != null) < if (filter.matches(tLine)) < informFilterListeners(tLine); return; >> > > catch (IOException e) < logger.logExceptionMessage(e, "IOException stderr"); >catch (InterruptedException e) < logger.logExceptionMessage(e, "InterruptedException waiting for external process"); >finally < if (tStreamReader != null) < try < tStreamReader.close(); >catch (IOException e) < // ignore >> > > 

On the calling side it looks like this:

 Thread tExtMonitorThread = new Thread(new Runnable() < public void run() < try < while (externalCommand == null) < getLogger().warning("Monitor: Sleeping until external command is found"); Thread.sleep(500); if (isStopRequested()) < getLogger() .warning("Terminating external process on user request"); if (externalCommand != null) < externalCommand.destroy(); >return; > > int tReturnCode = externalCommand.waitFor(); getLogger().warning("External command exited with code " + tReturnCode); > catch (InterruptedException e) < getLogger().logExceptionMessage(e, "Interrupted while waiting for external command to exit"); >> >, "ExtCommandWaiter"); ExternalProcessOutputHandlerThread tExtErrThread = new ExternalProcessOutputHandlerThread("ExtCommandStdErr", getLogger(), true); ExternalProcessOutputHandlerThread tExtOutThread = new ExternalProcessOutputHandlerThread("ExtCommandStdOut", getLogger(), true); tExtMonitorThread.start(); tExtOutThread.start(); tExtErrThread.start(); tExtErrThread.setFilter(new FilterFunctor() < public boolean matches(Object o) < String tLine = (String)o; return tLine.indexOf("Error") >-1; > >); FilterListener tListener = new FilterListener() < private boolean abortFlag = false; public boolean shouldAbort() < return abortFlag; >public void matched(String aLine) < abortFlag = abortFlag || (aLine.indexOf("Error") >-1); > >; tExtErrThread.addFilterListener(tListener); externalCommand = new ProcessBuilder(aCommand).start(); tExtErrThread.setProcess(externalCommand); try < tExtMonitorThread.join(); tExtErrThread.join(); tExtOutThread.join(); >catch (InterruptedException e) < // when this happens try to bring the external process down getLogger().severe("Aborted because auf InterruptedException."); getLogger().severe("Killing external command. "); externalCommand.destroy(); getLogger().severe("External command killed."); externalCommand = null; return -42; >int tRetVal = tListener.shouldAbort() ? -44 : externalCommand.exitValue(); externalCommand = null; try < getLogger().warning("command exit code: " + tRetVal); >catch (IllegalThreadStateException ex) < getLogger().warning("command exit code: unknown"); >return tRetVal; 

Unfortunately I don’t have to for a self-contained runnable example, but maybe this helps. If I had to do it again I would have another look at using the Thread.interrupt() method instead of a self-made stop flag (mind to declare it volatile!), but I leave that for another time. 🙂

Читайте также:  основы php на BlogGood.ru

Источник

How the stdin, stdout, stderr are closed [closed]

Want to improve this question? Update the question so it focuses on one problem only by editing this post.

In most modern programming languages, programmers don’t need to close the stdin , stdout , stderr . Does it mean that the operating system will handle the close of the stdin , stdout , stderr in general? Or for instance in java , the jvm will close the stdin , stdout , stderr when the running Java program exit ? There might be exceptions like some old programmers mentioned, so hereby I narrow down the language spectrum to Java, C, C++ only

The C++ library will flush anything that these streams have buffered up, before the program normally terminates. The process inherits the underlying files, so there’s nothing to close, but, technically, the operating system will release all resources used by the process when it terminates.

I’m sure that, at least, the part about the C++ library flushing the output streams is buried somewhere in the 1400+ pages that make up the current C++ standard. But this is such a minor detail, that, perhaps, if you explain the actual reason why you need an «authorized answer», then someone might be motivated enough to look it up.

2 Answers 2

Almost all programs run under a C run-time, so upon normal termination the rules of the C exit() function should apply. Per 7.22.4.4 The exit function of the C Standard:

Description

The exit function causes normal program termination to occur. No functions registered by the at_quick_exit function are called. If a program calls the exit function more than once, or calls the quick_exit function in addition to the exit function, the behavior is undefined.

First, all functions registered by the atexit function are called, in the reverse order of their registration, except that a function is called after any previously registered functions that had already been called at the time it was registered. If, during the call to any such function, a call to the longjmp function is made that would terminate the call to the registered function, the behavior is undefined.

Next, all open streams with unwritten buffered data are flushed, all open streams are closed, and all files created by the tmpfile function are removed.

Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS , an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE , an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.

For any process that’s not running under a standards-compliant C runtime, what happens upon process termination would be implementation-defined.

Источник

Java: Program stdout and stderr to some sort of handler

Is there a way to capture the stdout and stderror of my Java program line by line? Perhaps something similar to the way you can add a handler to a Logger instance using addHandler . edit: I don’t want to replace the default handlers—I still need the output to show up on the command line.

What is the reason for the requirement? If it’s for logging or debugging you should consider using a logging framework rather than stderr and stdout. If you’re on a *nix system you can just redirect the stdout and stderr to a file and tail the file.

I am writing a streaming API where you can get the console output for the program. So whatever goes into the console can also be viewed as a http stream.

3 Answers 3

By using System.setOut() and System.setErr() you can set standard output and error stream to any PrintStream, and capture everything.

ADDITION: I don’t know if there exist any elegant way to do this, but one way to do so is:
1. Save default output stream
PrintStream defaultOut = System.out;
(System.getOut() would be fun to have though)
2. Redirect System.out to the printstream you want (e.g. any file)
3. Instead of using System.out.println() use your print function, which does following:
print(Object o) defaultOut.println(o);//Assuming that defaultOut is visible in this function
System.out.println(o); >

The methods System.setOut and System.setErr allow you to change the PrintStream objects that the System.out and System.err variables refer to. You can use them to replace the default PrintStream objects with objects that capture output, or do whatever you want with it.

I don’t want to replace the PrintStreams because I still need the output to go to the command line.

Your code can take care of that:

  1. Create a subclass of OutputStream that writes all output to another OutputStream instance, and also captures the output. Make the «other» instance a constructort parameter.
  2. Get the current values of System.out and System.err .
  3. Instantiate your subclass twice, with the System.out and System.err values as constructor parameters respectively.
  4. Wrap those two instances as PrintStream instances.
  5. Call System.setOut and System.setErr to replace System.out and System.err with the PrintStream instances.

Источник

Оцените статью