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.
Related
I am using ProcessBuilder to run FFMPEG to convert and label some of my MP3-Files.
Manually using the following in a .bat file works as expected:
"E:\Dokumente\workspace\MusicBot\ffmpeg\bin\ffmpeg.exe"
-i "The Glitch Mob - We Can Make The World Stop.mp4"
-metadata author="The Glitch Mob"
-metadata title="We Can Make The World Stop"
-ab 320k "mob.mp3"
Now what i am trying to achieve using java's ProcessBuilder
ProcessBuilder pr = new ProcessBuilder(FFMPEG_PATH,
"-i", target.getAbsolutePath(),
"-metadata", "title=\"We Can Make The World Stop\"",
"-metadata", "author=\"The Glitch Mob\"",
"-ab", "320k",
tar.getAbsolutePath());
results in a [NULL # 000000000032f680] Unable to find a suitable output format for 'Can'.
Using title and author without spaces in them works, however.
The double quotes on the command line are there to tell the shell interpreter not to split your string into multiple parameters. This is to ensure that the application receives title=We Can Make The World Stop as a single argument.
Since ProcessBuilder handles multiple command line arguments explicitly, there's no need for escaping whitespace when calling it.
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?
I bumped into this problem today when setting up a local set of communicating programs. Basically one of my applications is sending some data to another, and part of this data is a string containing a command to execute (like you would from the command-line). Let's say, for example:
g++ foo.cc bar.cc -o foobar
is the command sent by my first application. The second application, which receives the command (amongst other things), needs to execute this command after doing some other processing.
Now, at first I thought this would be trivial using a ProcessBuilder:
String exampleCommand = "g++ foo.cc bar.cc -o foobar";
ProcessBuilder builder = new ProcessBuilder(exampleCommand);
builder.start().waitFor();
However this is where the problem occurs.
CreateProcess error=2, The system cannot find the file specified
Okay, no worries I guess I can't just dump the whole thing into the builder. The first part of the command is usually a trivial string so I thought I could probably get away with a split around the first ' ' to separate the program name and arguments.
String exampleCommand = "g++ foo.cc bar.cc -o foobar";
String[] parts = exampleCommand.split(" ", 2);
ProcessBuilder builder = new ProcessBuilder(parts[0], parts[1]);
builder.start().waitFor();
And this brought me a little closer, the g++ file could now be found correctly, however after examining the stderr of g++ I found that the following error had occurred:
g++.exe: error: foo.cc bar.cc -o foobar: No such file or directory
At this point I realised that the ProcessBuilder class must be escaping all arguments passed to it in preparation for the command-line (hence the reason it usually takes arguments as an array of individual arguments rather than just a predefined argument string).
My question is, "Is there any way to pass a raw string of arguments to a ProcessBuilder and say THERE, execute EXACTLY this?"
Because the command comes from another application and is in no way static I can't just break the arguments down into an array beforehand and pass them to the ProcessBuilder constructor properly. The arguments are not so trivial that simply splitting the string around a ' ' will work properly either; arguments might contain spaces escaped with double quotes. For example:
g++ "..\my documents\foo.cpp" bar.cpp -o foobar
Could be a command coming from the application and splitting that string around ' ' and passing it to the ProcessBuilder will result in corrupt arguments.
If there is no proper way to do this can someone please point me to a standalone command line argument parser (in Java) that can turn a command-line string into a valid String[]?
Okay I feel rather foolish now but I achieved my desired result by simply reverting back to the good old Runtime.getRuntime().exec(...). I'll leave the question up in case anyone is as silly as me and find it useful.
String exampleCommand = "g++ foo.cc bar.cc -o foobar";
Runtime sys = Runtime.getRuntime();
sys.exec(exampleCommand);
Easy.
A comment to the Runtime.getRuntime().exec(...) solution:
The Runtime.getRuntime().exec(...) is not good anymore. In java executed on OSX El Capitan, 'Runtime.getRuntime().exec(...)' contains an error that sometimes closes the opened process when the java program exits. It works fine on previous OSX versions. However, ProcessBuilder works on all OSX versions.
(Haven't posted enough to have a enough rep points to make this as a normal comment.)
I want to open a file in .jar application and I want to use java to do this. Explaining, for example I have the file SF_Antivalent.xml and I want to open it with uppaal.jar. How do I do this using Java. I've written the following code, but it doesn't work.
public class test7 {
public static void main(String[] args){
Runtime rt=Runtime.getRuntime();
String file="C:\\Users\\V\\Documents\\diplwmatiki\\SFBs\\SF_Antivalent.xml";
Process p=rt("C:\\Windows\\System32\\java.exe", "-jar", "C:\\Users\\"
+ "V\\Documents\\uppaal-4.0.13-aca\\uppaal-4.0.13\\uppaal.jar" + file);
}
}
and I get this error: the method rt(String, String, String) is undefined for the type test.
Is there something to do?
You question is a little confusing, however, I believe you want to run some application and pass the XML file as a parameter to it...
The problem is, you're treating rt as a function/method, not an object. Runtime has the an exec method used to execute external commands, for example...
Runtime rt=Runtime.getRuntime();
String file="C:\\Users\\V\\Documents\\diplwmatiki\\SFBs\\SF_Antivalent.xml";
Process p=rt.exec(new String[]{
"C:\\Windows\\System32\\java.exe",
"-jar",
"C:\\Users\\V\\Documents\\uppaal-4.0.13-aca\\uppaal-4.0.13\\uppaal.jar",
file});
Also, each command or argument you want to send to this external process must be it's own element within the array you pass to this method
This means tha "V\\Documents\\uppaal-4.0.13-aca\\uppaal-4.0.13\\uppaal.jar" + file won't actually have the effect you think it will.
I'd also recommend that you use ProcessBuilder over Runtime#exec, but that's me.
The reason you are getting the error is because rt is a Runtime object, not a method. To call a method of rt do this:
rt.someMethodName();
With the code above you cannot get XML file, you're trying to execute something, instead of opening file inside JAR archive
Look into getResourceAsStream, this will give you possibility to load any file from JAR
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.