I'm not sure if this is possible, especially since Java runs through a VM, but can I call gnuplot from within Java? Perhaps I could have Java open a terminal and input
gnuplot
plot ...
etc?
Use gnujavaplot.
If you can get gnuplot to take all input from the command line or standard input (or read it from a file) and write its output to files as well, then there should be no problem doing this using ProcessBuilder.
This works on Debian:
String[] s = {"/usr/bin/gnuplot",
"-e",
"set term jpeg large size 800,600;set autoscale; set grid;set format y \"%0.f\";set output \"plot.jpg\";set xdata time;set timefmt \"%Y-%m-%d-%H:%M:%S\";set xlabel \"Dates\";set ylabel \"Data transferred (bytes)\";plot \""+x+"\" using 1:2 title \"Total:"+tot+"\" with linespoints;"
};
try {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(s);
InputStream stdin = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
System.err.println("gnuplot:"+line);
int exitVal = proc.waitFor();
if (exitVal != 0)
log("gnuplot Process exitValue: " + exitVal);
proc.getInputStream().close();
proc.getOutputStream().close();
proc.getErrorStream().close();
} catch (Exception e) {
System.err.println("Fail: " + e);
}
Use the JavaGnuplotHybrid library.
It is very light weight (only 3 core classes) and enables hybrid programming with Java and Gnuplot.
Hybrid programming with Java and Gnuplot
Very light weight (just three core Classes)
Use tags in Gnuplot code to execute functions or get fields' values
in Java.
Support both synchronized and asynchronized running of Gnuplot in
Java. (synchronized: your java program will wait until you close the
popped Gnuplot window; asynchronized: you java program will not
wait.)
Capture error/normal text output of Gnuplot to the java terminal
Read Gnuplot code from xml files
Support Gnuplot code template.
For more details:
Project page: https://github.com/mleoking/JavaGnuplotHybrid
Examples: https://github.com/mleoking/JavaGnuplotHybrid/blob/master/javagnuplothybrid/doc/examples.md
You can launch any external application using the "exec" commands.
http://java.sun.com/javase/6/docs/api/java/lang/Runtime.html
See this page for a few examples.
http://www.rgagnon.com/javadetails/java-0014.html
EDIT: I forgot about ProcessBuilder. Michael Borgwardt's answer is a more robust solution.
Related
I am trying to call a python script from a java/tomcat6 webapp. I am currently using the following code:
Process p = Runtime.getRuntime().exec("python <file.py>");
InputStream in = p.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader b = new BufferedReader(isr);
logger.info("PYTHON OUTPUT");
String line = null;
while ( (line = b.readLine()) != null){
logger.info(line);
}
p.waitFor();
logger.info("COMPLETE PYTHON OUTPUT");
logger.info("EXIT VALUE: "+p.exitValue());
I can't really see any output in the catalinia.out file from the python script and using an adapter library like jython is not possible as the script relies on several machine learning libraries that need python's Numpy module to work.
Help?
The explanation is probably one (or more) of following:
The command is failing and writing error messages to its "stderr" fd ... which you are not looking at.
The command is failing to launch because the command name is incorrect; e.g. it can't be found on $PATH.
The command is trying to read from its stdin fd ... but you haven't provided any input (yet).
It could be a problem with command-line splitting; e.g if you are using pathnames with embedded spaces, or other things that would normally be handled by the shell.
Also, since this is python, this could be a problem with python-specific environment variables, the current directory and/or the effective user that is executing the command.
How to proceed:
Determine if the python command is actually starting. For instance. "hack" the "" to write something to a temporary file on startup.
Change to using ProcessBuilder to create the Process object. This will give you more control over the streams and how they are handled.
Find out what is going to the child processes "stderr". (ProcessBuilder allows you to redirect it to "stdout" ...)
So I have this Java program that creates processes that run a certain C program on the terminal (unix), and I need to notify the Java program when something happens in the C program (before the termination). How can I do this? I know that I'm gonna need signals, but I don't have much experience on the subject.
Thanks in advance!
EDIT: This the changes I made to the java, after calling the process:
InputStream stdout = p.getInputStream();
InputStreamReader isr = new InputStreamReader(stdout);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<INPUT>");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("</INPUT>");
int exitVal = p.waitFor();
System.out.println("Process exitValue: " + exitVal);
I what I did in the C when I want to notify the java:
char buff[20];
size_t nbytes;
ssize_t bytes_written;
int fd;
strcpy(buf, "This is a test\n");
nbytes = strlen(buf);
bytes_written = write(1, buff, nbytes);
But after running it I only get:
INPUT
/INPUT
Process exitValue: 0
One of the ways is reading your C program's stdout
Process p = Runtime.getRuntime().exec("c.exe");
InputStream stdout = p.getInputStream();
now C program can talk to Java program
You can create a socket using c program and send it to java socket server. You can search on goole to find out sample.
Easiest way to communicate between a Java program and another program spawned by it, is using the FIFO streams that are set up when you launch a subprocess. So, for example, if you launched your subprocess using Runtime.exec() or using ProcessBuilder, you have an object of type Process. By calling its getInputStream() you can have access to the process' stdout.
In the native code, just print your signals out to stdout and they can be read by the Java process.
You can use Signals with Java, but this is not the best mechanism. I would look at using JNI, JMS, Socket, RPC or some other solution first. The problem with signals is that it doesn't allow you to transmit much information and it's the easiest to get right or debug.
For more details on signal handling and Java
http://www.oracle.com/technetwork/java/javase/signals-139944.html
http://www.ibm.com/developerworks/java/library/i-signalhandling/ (link dead)
http://ringlord.com/dl/Signals-in-Java.pdf
I want to call an "interactive" Perl script from a Java program. Just for the clarity, the other way around (from Perl to Java) is not good for me.
The script is interactive in the sense that it requires a small configuration dialog with the user. For example, calling the script in cmd.exe would lead to a dialog like:
Do you want to overwrite the old settings? [yes,no (default=no)]
and the user should choose between writing yes, no or nothing at all in the command line.
And depending on the user choice another message would appear: "Do you want to...." and the user will respond etc etc. I think you got the picture.
My question is how can I have the same dialog with the user when the script is called in a Java program? I mean, how can I capture the script's questions to the user, show them to user and then send the user's answer (got in the Java program) to the script?
A simple Runtime.getRuntime().exec() doesn't work in this case.
Hope I expressed clear enough the question.
Thank you for your help!
You must use getInputStream/getOutputStream methods to get access to stdin and stdout of perl stript. You can read and write to these streams to simulate user's behavior
OutputStream stdin = null;
InputStream stderr = null;
InputStream stdout = null;
Process process = Runtime.getRuntime ().exec ("...");
stdin = process.getOutputStream ();
stderr = process.getErrorStream ();
stdout = process.getInputStream ();
// "write" the parms into stdin
String line = "data\n";
stdin.write(line.getBytes());
stdin.flush();
stdin.close();
// clean up if any output in stdout
BufferedReader brCleanUp =
new BufferedReader (new InputStreamReader (stdout));
while ((line = brCleanUp.readLine ()) != null) {
//System.out.println ("[Stdout] " + line);
}
brCleanUp.close();
// clean up if any output in stderr
brCleanUp =
new BufferedReader (new InputStreamReader (stderr));
while ((line = brCleanUp.readLine ()) != null) {
//System.out.println ("[Stderr] " + line);
}
brCleanUp.close();
This is a job for Expect. In Java: ExpectJ, expect4j
If (1) your call is from Java to Perl, and (2) you are not parsing the Perl script itself, why not use a JOptionPane.showConfirmDialog() from the Java code? Shouldn't be a big deal if a Yes/No is all your are getting from the script. Whatever you are printing to display to the user can be included in that confirm dialog as a plain ASCII text, too.
Im developing a simple console Application using java. The code is given below
` try {
File file = new File("writer.txt");
writer = new BufferedWriter(new FileWriter(file));
Process myProcess = Runtime.getRuntime().exec("jps -l");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
myProcess.getInputStream()));
String line = stdout.readLine();
while (line != null) {
if (line.contains(".jar")) {
writer.write(line);
System.out.println(line);
}
line = stdout.readLine();
}
writer.close();
}
`
The code will display the currently running the jar in my windows. The output format is displayed 2356 Timeout.jar I want to display it only Timeout.jar How to remove that integer values. Thanks in advance.
Assuming you have "2356 Timeout.jar" in line, this will return just the jar name:
line.substring(line.indexOf(" ") + 1);
I think there must be an easier way to get the running jar though. I did a quick search and you may want to look at these questions:
How to get the path of a running JAR file?
http://arstechnica.com/civis/viewtopic.php?f=20&t=261563
You could:
Apply a regular expression to line before writing it out. (Think start-of-line, then integers, ending at the first whitespace)
Use ls (or dir) as your exec process instead of jps
Just grab the directory listing directly instead of via the external process as per below:
File dir = new File("directoryName");
String[] children = dir.list();
Doing what you have via JPS is probably not a good idea if this isn't a quick one-off app or a learning exercise because of the following note from the jps man page:
NOTE- You are advised not to write scripts to parse jps output since
the format may change in future releases. If you choose to write
scripts that parse jps output, expect to modify them for future
releases of this tool.
Tokenizing the result is one way.
if you are in unix, use awk to get the second field.
If you are using a Linux based OS,
Instead of
Process myProcess = Runtime.getRuntime().exec("jps -l");
try this one
Process myProcess = Runtime.getRuntime().exec("jps -l | cut -d \" \" -f2");
How can I write a program in Java that will execute another program? Also, the input of that program should be given from our program and the output of that program should be written into a file.
This is my small set of code to get its output:
Process p = Runtime.getRuntime().exec("C:\\j2sdk1.4.0\bin\\helloworld.java");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null)
System.out.println(line);
input.close();
This was my set of code but this throws an IOException.
The API that Java offers for this is the ProcessBuilder. It is relatively straightforward to set working directory and pass parameters.
What is a little tricky is passing STDIN and reading STDERR and STDOUT, at least for non-trivial sizes thereof, because you need to start seperate threads to make sure the respective buffers get cleared. Otherwise the application that you called might block until it can write more output, and if you also wait for that process to finish (without making sure that STDOUT gets read), you will deadlock.
You can use java.lang.Process and java.lang.ProcessBuilder. You interact with the input/output of the process using getInputStream/getOutputStream/getErrorStream.
However, there's an Apache Commons library called Exec which is designed to make all of this easier. (It can normally get quite hairy when it comes to quoting command line parameters etc.) I haven't used Exec myself, but it's worth checking out.
When you only want to start other programms, you can use the exec method like this:
Runtime r = Runtime.getRuntime();
mStartProcess = r.exec(applicationName, null, fileToExecute);
StreamLogger outputGobbler = new StreamLogger(mStartProcess.getInputStream());
outputGobbler.start();
int returnCode = mStartProcess.waitFor();
class StreamLogger extends Thread{
private InputStream mInputStream;
public StreamLogger(InputStream is) {
this.mInputStream = is;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(mInputStream);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
exec:
public Process exec(String command, String envp[], File dir)
#param command a specified system command.
#param envp array of strings, each element of which
has environment variable settings in format
<i>name</i>=<i>value</i>.
#param dir the working directory of the subprocess, or
<tt>null</tt> if the subprocess should inherit
the working directory of the current process.
Please do not edit your question so that it does not fit the original answers anymore.
If you have follow-up question, clearly mark them as such, or ask them as a seperate questions, or use comments or something.
As for your IOException, please give the error message it shows.
Also, it seems as if you are trying to run a ".java" file directly. That will not work. The methods described here are to launch native binary executables. If you want to run a ".java" file, you have to compile it to a class, and the invoke that class' main method.
What platform are you in?
If you are on *nix you can type:
java MyProgram | myexternalprogram > myfilename.txt