This is my code for run a java file in other java application but i dont knoow what to do if the program takes only bufferedinputs ??
try {
Runtime rt = Runtime.getRuntime();
// compile the java file
Process pr = rt.exec("javac Main.java");
pr.waitFor();
// run the java file
pr = rt.exec("java Main " + inputs.toString()); // using this i can give command line arguments
pr.waitFor();
}
This is my code i can give command line arguments at run time but what if i want to give bufferedinput to the program ?
Thanks in advance
You state:
This is my code for run a java file in other java application but i dont knoow what to do if the program takes only bufferedinputs ??
To attach to another processes input and output streams, look at the API for the Process class where you'll find and use the getErrorStream(), getInputStream() and getOutputStream() methods. You can then wrap your Input and Output and Error Streams in their respective Buffered Streams.
Note however that you should be wary of common pitfalls which are well explained in the slightly dated article, When Runtime Exec Won't
Having said this, you're far better off using the Java classes themsevels rather than running it in another JVM. Is there a reason that you can't do this? And what do you mean by "buffered" input?
Related
I'm trying to train a neural network to play Halite 3. The provided interface is a bash script which:
1. compiles my bot
2. calls the binary file with a string to run the bot java myBot
I'm trying to run this script from Java to train the network.
I've tried using a ProcessBuilder to run the script as well as the binary in the script. Running the script produces no output, and using echo I've determined that the program terminates when javac is called in the script. Removing that call, it terminates when the program is run.
I've tried calling the program directly as well using ProcessBuilder, and this does indeed produce output. The issue is it doesn't run the bots properly saying it can't find the file. I've tried changing the path to be relative to different directory levels as well as the absolute path (the java command doesn't seem to like absolute paths?).
Calling the binary directly:
List<String> cmd = new ArrayList<>();
cmd.add(dir+ "/src/halite");
// Replay
cmd.add("--replay-directory");
cmd.add(dir+"/replays/");
// Options
cmd.add("--results-as-json");
cmd.add("--no-logs");
// Dimensions
cmd.add("--width");
cmd.add("16");
cmd.add("--height");
cmd.add("16");
// Players
cmd.add("\"java -cp . myBot\"");
cmd.add("\"java -cp . myBot\"");
Process proc = new ProcessBuilder(cmd).start();
InputStream is = proc.getInputStream();
Scanner s = new Scanner(is);
while (s.hasNext()){
System.out.println((String) s.next());
}
This code does produce a JSON, however, I get an error in my logs saying that the bots do not run.
I am writing a Java application that needs to execute the unix cat command using ProcessBuilder. I know I can use the arguments to the ProcessBuilder object to specify the file for cat to use. However, to standardize the interface, how would I use redirectInput() instead to pass the input file?
I'm assuming this would work as I can perform cat < foo.txt in the command line, which is equivalent to redirectInput() in ProcessBuilder (right?)
Help is much appreciated :)
Why not just try it?
I've written a simple test code:
new ProcessBuilder("cat")
.redirectInput(new File("/tmp/test", "i.txt"))
.redirectOutput(new File("/tmp/test", "o.txt"))
.start()
.waitFor();
And it successfully copied some text from i.txt to o.txt.
I am trying to make a java program that automatically converts wtv files in an input folder to mpg files in output folder. The twist is that I make it run periodically, so it acts as a synchronizer.
The following code works for converting the .wtv to a .dvr-ms, which is required by ffmpeg since it cannot convert .wtv files directly.
Process p = Runtime.getRuntime().exec("C:\\Windows\\ehome\\WTVConverter C:\\Users\\Andrew\\Desktop\\test\\input\\input.wtv C:\\Users\\Andrew\\Desktop\\test\\output\\input.dvr-ms");
p.waitFor();
WTVConverter has no problems running from a java application. ffmpeg is a different story. Once the above line runs, I then run this...
Process p = Runtime.getRuntime().exec("ffmpeg\\bin\\ffmpeg -y -i \"C:\\Users\\Andrew\\Desktop\\test\\output\\input.dvr-ms'" -vcodec copy -acodec copy -f dvd \"C:\Users\Andrew\Desktop\test\output\input.mpg\"");
p.waitFor();
Suddenly, there is a problem... The application ffmpeg shows up in the task manager, but it's cpu usage is 0, and no mpeg files is being generated. If I force the java application to close, though, suddenly it starts working! Huh?
What reason would there be for a command line application to wait for its calling application to quit before it executes? I'm not incredibly command line savvy, so I don't really know how to diagnose this problem.
Bah, this always happens. I post a question, and THEN I figure it out on my own. Turns out, ffmpeg expects you to read in its text output before it loads each frame. If a calling program does not do this, it simply waits. If there is no calling program, I assume that it just outputs it nowhere. What I did is ran the program as usual, but also read in text from the process's input stream like so...
Process p = Runtime.getRuntime.exec(".....");
final Scanner in = new Scanner(p.getInputStream());
new Thread()
{
#Override
public void run()
{
System.out.println(in.nextLine());
}
}.start();
Lesson learned, I guess.
I have this piece of code that compiles a class called tspClassName, when I compile using this code:
Process compileProc = null;
try {
compileProc = Runtime.getRuntime().exec("javac -classpath ."
+ File.separator + "src" + File.separator
+ File.separator + "generated." + tspClassName + ".java -d ." + File.separator + "bin");
// catch exception
if (compileProc.exitValue() != 0)
{
System.out.println("Compile exit status: "
+ compileProc.exitValue());
System.err.println("Compile error:" +
compileProc.getErrorStream());
it outputs this:
"Compile exit status: 2
Compile error:java.io.FileInputStream#17182c1"
The class tspClassName.java compiles without errors otherwise, so I am guessing it has to do with the path,and in my eclipse project, the tspClassName.java resides in package homework4.generated inside src, is there something wrong with the path that I use in the code?
thanks
Your Java code runs a command that looks something like this:
javac -classpath ./src//generated.ClassName.java -d ./bin
I don't think that's what you want. I think you need to change your Java code so it maybe generates something like:
javac -classpath . src/generated/ClassName.java -d ./bin
^
Note the space after the classpath (".").
You can use the javax.tools.JavaCompiler or JCI that wrap this functionality.
I recommend doing something like this:
String command = String.format(
"javac -classpath . src%1$sgenerated%1$s%2$s.java -d .%1$sbin",
File.separator,
tspClassName
);
LOG("Executing " + command);
//... exec(command) etc
... where LOG is whatever your logging framework uses to log the command to be executed. This will help debugging immensely, since it was pointed out that the command you built is ill-constructed.
Alternately you can also build the string using replace
String command =
"javac -classpath . src/generated/ClassName.java -d ./bin"
.replace("/", File.separator)
.replace("ClassName", tspClassName);
This is perhaps more readable.
On draining Process streams
OP's comment suggests that waitFor() never returns. This is likely caused by compilation errors/warnings in javac process.
From the API:
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.
You need to continuously drain the Process.getOutputStream() et.al.
See also
Java Puzzlers, Puzzle 82: Beer Blast
Related questions
Draining standard error in Java
I think the proper way to do this kind of work is programatically using the javax.tools API, not an external process:
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler()
Reference:
ToolProvider.getSystemJavaCompiler()
The problem could be with the file location instead of using single value parameter for exec()
try 3 parameter method which has the command, environment and location as parameters which helps us to move to the specified location and execute the command
check 6 and 8 methods for reference
http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html
Process compile = Runtime.getRuntime().exec("javac "+fname,null,new File(dir));
firstly you should use apache exec library if you want to use processes like that. Apache exec library makes things very easy.
Secondly you should print your std output and std error streams of your process which you are executing. Without them its no way to know whats being executed and what's it doing.
Thirdly, try to print the full cmd line which the process is executing. Copy that cmd line and try to run it manually. Most of the time you would find your issues this way.
And finally if your aim is just to compile a class / generate or modify a class file at runtime give this a good read and try. It has examples too. You could also try code generation / class manipulation libraries like BCEL, JavaAssist etc.
Best of luck.
What is the simplest way to call a program from with a piece of Java code? (The program I want to run is aiSee and it can be run from command line or from Windows GUI; and I am on Vista but the code will also be run on Linux systems).
Take a look at Process and Runtime classes. Keep in mind that what you are trying to accomplish is probably not platform independent.
Here is a little piece of code that might be helpful:
public class YourClass
{
public static void main(String args[])
throws Exception
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("name_of_your_application.exe");
int exitVal = proc.exitValue();
System.out.println("Process exitValue: " + exitVal);
}
}
One question in S.O. discussing similiar issues. Another one. And another one.
You can get a runtime instance using Runtime.getRuntime() and call the runtime's exec method, with the command to execute the program as an argument.
For example:
Runtime runTime = Runtime.getRuntime ();
Process proc = rt.exec("iSee.exe");
You can also capture the output of the program by using getting the InputStream from the process.
The difficulty you will run into is how to get the application to know the path. You may want to use an xml or config file, but if you use this link, it should explain how to run a file:
http://www.javacoffeebreak.com/faq/faq0030.html
You may also want to consider passing in some kind of argument to your program to facilitate finding the specific program you want to run.
This could be with command line arguments, properties files or system properties.