Reputation: 6747
I am making a program that will have the ability to run the java compiler and jvm right from within it (Don't ask me why I am reinventing the wheel, if your reply does not help, save it, I am already quite frustrated spending hours on solutions that do not work!). So far I have managed it to track whenever I input something in my textField that starts with java so that it will actually wrap up the text and give it a run like so:
if(String.valueOf(object).startsWith("java")){
try{
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(String.valueOf(object));
}
catch(Exception e){gsc.mainWindow.printf("error");}
Consider gsc.mainWindow.printf(...);
my output to a JTextArea within a JFrame.
What I have managed now is to run the commands, but anything fails I shall be able to print it directly to my output. I know this has been answered a ton of times before, read about 10 ways to do this, but none of them worked or was understandable to the point that I could run it. I need the code to be simple enough as this will have to be outputting what the proccess will be writing in the default system's Console (cmd,terminal) and then stop (I thought that this can be a method call alltogether). I am quite bad with this kind of stuff, even a multithread solution could fit my needs, nothing too professional really, I just need it to work. Any information you need, ask away! Thanks in advance! :)
Upvotes: 1
Views: 2143
Reputation: 5267
I don't know you if you want to read this, but you know, in the Java world, you should always look for a solution before implementing your own. And the solution for common problems, most of the time, comes from Apache Commons or other Apache projects. Saying that everything but your solution doesn't work or is too complicated to you will only cost you time and money (and your job, eventually).
Apache Commons Exec is what you need to solve your problem faster and easier.
---- Edit ----
Here is some code of how to capture the output of the child process. There's a class just for it, the PumpStreamHandler:
DefaultExecutor exec = new DefaultExecutor();
PumpStreamHandler streamHandler = new PumpStreamHandler();
exec.setStreamHandler(streamHandler);
CommandLine commandline = CommandLine.parse(command); //where command is your command line
exec.execute(commandline);
---- Edit 2 ----
Here is the copy-paste solution you want to capture the message using an OutputStream
:
public abstract class LogOutputStream extends OutputStream {
protected static final String LINE_SEPERATOR = System.getProperty("line.separator");
public static final int DEFAULT_BUFFER_LENGTH = 2048;
protected boolean hasBeenClosed = false;
protected byte[] buf;
protected int count;
private int bufLength;
public LogOutputStream() {
bufLength = DEFAULT_BUFFER_LENGTH;
buf = new byte[DEFAULT_BUFFER_LENGTH];
count = 0;
}
public void close() {
flush();
hasBeenClosed = true;
}
public void write(final int b) throws IOException {
if (hasBeenClosed) {
throw new IOException("The stream has been closed.");
}
if (b == 0) {
return;
}
if (count == bufLength) {
final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
final byte[] newBuf = new byte[newBufLength];
System.arraycopy(buf, 0, newBuf, 0, bufLength);
buf = newBuf;
bufLength = newBufLength;
}
buf[count] = (byte) b;
count++;
}
public void flush() {
if (count == 0) {
return;
}
if (count == LINE_SEPERATOR.length()) {
if (((char) buf[0]) == LINE_SEPERATOR.charAt(0)
&& ((count == 1) ||
((count == 2) && ((char) buf[1]) == LINE_SEPERATOR.charAt(1)))) {
reset();
return;
}
}
final byte[] theBytes = new byte[count];
System.arraycopy(buf, 0, theBytes, 0, count);
log(new String(theBytes));
reset();
}
private void reset() {
count = 0;
}
public abstract void log(String message);
}
Then just create a subclass of it, implement the public void log(String message)
with the code that updates the UI, and it's done.
Upvotes: 4