I am trying to run a binary file, which is Genia Sequence Splitter through java code. This Binary file is type x-executable and has no extension. I can run the file in terminal by using ./geniass arg1 arg2
where arg1 is input file arg2 is output file
I want to automate this process. I tried using this code
public class geniaSSTag {
public static void geniaSS(String inputFile){
System.out.println("Input file: "+inputFile);
String[]cmd={"bash","geniass/./geniass","in.txt","out.txt"};
try {
String errOutput="";
Process process = Runtime.getRuntime().exec(cmd);
String s = "";
BufferedReader br = new BufferedReader(new InputStreamReader(process
.getInputStream()));
while ((s = br.readLine()) != null)
{
s += s + "\n";
}
System.out.println(s);
BufferedReader br2 = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while (br2.ready() && (s = br2.readLine()) != null)
{
errOutput += s;
}
System.out.println(errOutput);
} catch (IOException ex) {
Logger.getLogger(geniaSSTag.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
But I get this error when I try to run
geniass/./geniass: geniass/./geniass: cannot execute binary file
How can I solve this. Any help is appreciated.
Thank you
When you run the program, is the executable relative to the program's starting directory in the manner that it lies in "./genias/genias"? Note that the "/./" doesn't do anything except waste space, as it is shorthand for "the subdirectory that links back to the current directory".
Perhaps your "genias" executable isn't in a subdirectory named "genias", or the launching program is being launched from a different directory and can't find "genias/genias" relative to it's directory.
As suggested elsewhere, you can fix this by using an absolute path in the launching command. However, sometimes this just isn't flexible enough if you want multiple copies installed.
I would try first to run the command pwd from Java to see where you actually are. Then you can change the path to your executable accordingly. I guess using the path /home/xxx/yyy/geniass would always work.
Also there is a different version of Runtime.exec() which takes a working directory as an argument.
Try:
String[]cmd={"/full/path/to/geniass","in.txt","out.txt"};
Instead
Related
I am new to both Java and Linux, I was trying to use some Runtime.exec() commands that would allow my program to execute commands in Linux such as "cd /mnt/" and "ls --group-directories-first" to list files and directories contained in /mnt/ but I think I am making a problem with the execution.
I tried my code to only include the "ls --group-directories-first" and it worked like a charm, only problem was, it only listed subdirectories and files in the projects folder. I wanted to make my program go to /mnt/ first so I made my command line to a command array by using exec(String[] cmdarray) format as process1 = Runtime.getRuntime().exec(new String[]{"cd /mnt/","ls --group-directories-first"}); and when I ran it on linux, it just got executed without any printed runtime errors but also without any feedback/printed lines.
Here is my code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class linCom {
public static void main(String args[]) {
String s;
Process p;
try {
p = Runtime.getRuntime().exec("ls --group-directories-first");
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = br.readLine()) != null)
System.out.println("line: " + s);
p.waitFor();
System.out.println ("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {}
}
}
This worked and printed out:
"line: DummyFolder1
line: linCom.class
line: linCom.java
exit: 0"
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class linCom {
public static void main(String args[]) {
String s;
Process p;
try {
p = Runtime.getRuntime().exec(new String[]{"cd /mnt/","ls --group-directories-first"});
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = br.readLine()) != null)
System.out.println("line: " + s);
p.waitFor();
System.out.println ("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {}
}
}
This just got executed with no printed lines.
I expected my program to just go to the /mnt/ directory and print out subdirectories and files on there, but it just got executed with no visible runtime errors and no printed lines.
I have looked at other entries but could not find any answer to my problem.
EDIT: I changed "no errors" with "no error messages" to make it clear that if program had any errors, I did not get any feedback about it.
Here's where the UNIX process model can be confusing.
What you have tries to run the program named cd /mnt/ with the first parameter of ls --group-directories-first . Unix programs can be named anything (they're just filenames) but there's no program named cd /mnt. And anyway, the cd operation is actually performed by a shell, not as a forked/execed program.
You hope to run this shell command from your Java program: cd /mnt/; ls --group-directories-first . The trouble is, Java's .exec() method does not give you a shell, so shell commands don't work.
You can try this instead. It's like running the shell command
/bin/sh -c "cd /mnt/; ls --group-directories-first"
With this, you start a shell, then tell it to run -cthe command you want.
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh",
"-c",
"cd /mnt/; ls --group-directories-first"});
But it's quite dependent on the machine where your Java program runs, so be careful.
Reference: How to invoke a Linux shell command from Java
Do not use an external process just to list files. Java has plenty of ways to do that. All of them are in the Files class. For example:
Path dir = Paths.get("/mnt");
try (Stream<Path> files = Files.list(dir).sorted(
Comparator.comparing((Path p) -> !Files.isDirectory(p))
.thenComparing(Comparator.naturalOrder()))) {
files.forEach(System.out::println);
}
Do you really need to use Runtime.exec()comands? That would make your code platafform dependent.
You could use File.listFiles():
File folder = new File("/mnt");
for (File f : folder.listFiles()) {
System.out.println(f.getName());
}
That would make the code less plataform dependent
I am currently working on a java project which automatically generates texts files with LaTeX source code. These files are written to the hard drive at a know directory. Instead of having to manually compile the LaTeX source into a pdf myself, I want to use Runtime.getRunTime().exec().
I downloaded and installed BasicTeX. I do know that it is working properly. I can call the following in a new terminal window and the pdf is properly generated with no errors. Like this:
Kyles-MacBook-Pro:~ kylekrol$ cd Documents/folder/Report
Kyles-MacBook-Pro:Report kylekrol$ pdflatex latexDocument.txt
So I simply tried to use the following code before my program closed to compile the pdf:
private static void compileLatexMac(String path) {
String s = null;
try {
System.out.println("cd " + path.substring(0, path.length() - 1) + " && pdflatex latexDocument.txt");
Process p = Runtime.getRuntime().exec("cd " + path.substring(0, path.length() - 1) + " && pdflatex latexDocument.txt");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
System.out.println("outputs:");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("errors:");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
When I run this all I get back is the following without a pdf or a log file.
cd /Users/kylekrol/Documents/folder/Report && pdflatex latexDocument.txt
outputs:
errors:
I am not really sure what to make of this or why it isn't working - especially because I can call cd /Users/kylekrol/Documents/folder/Report && pdflatex latexDocument.txt from Terminal and it runs as desired.
If someone could point out what I'm missing here that'd be great. Thanks!
I ended up running into more issues using the three argument exec() command when running the jar file by double clicking on it. I fixed this by calling the following command which uses an extra pdflatex argument and only absolute paths.
Runtime.getRuntime().exec("pdflatex -output-directory=" + path.substring(0, path.length() - 1) + " " + path + "latexDocument.txt");
The operator && is expanded by the shell. Runtime.exec does not expand this operator and just attempts to executes the cd command with the remainder of the command line as arguments. Thus, your pdflatex command is never run.
If you want to run pdflatex with a particular working directory, use the three-argument version of Runtime.exec.
I am getting an exception like java.io.IOException: Cannot run program cat /home/talha/* | grep -c TEXT_TO_SEARCH": error=2, No such file or directory while executing the command below despite that there are no issues when I execute the same command through the terminal. I need to execute and return the output of the command below:
cat /home/talha/* | grep -c TEXT_TO_SEARCH
Here is the method used to execute commands using Runtime class:
public static String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
Runtime.exec does not use a shell (like, say, /bin/bash); it passes the command directly to the operating system. This means wildcards like * and pipes (|) will not be understood, since cat (like all Unix commands) does not do any parsing of those characters. You need to use something like
p = new ProcessBuilder("bash", "-c", command).start();
or, if for some bizarre reason you need to stick to using the obsolete Runtime.exec methods:
p = Runtime.getRuntime().exec(new String[] { "bash", "-c", command });
If you are only running that cat/grep command, you should consider abandoning the use of an external process, since Java code can easily traverse a directory, read lines from each file, and match them against a regular expression:
Pattern pattern = Pattern.compile("TEXT_TO_SEARCH");
Charset charset = Charset.defaultCharset();
long count = 0;
try (DirectoryStream<Path> dir =
Files.newDirectoryStream(Paths.get("/home/talha"))) {
for (Path file : dir) {
count += Files.lines(file, charset).filter(pattern.asPredicate()).count();
}
}
Update: To recursively read all files in a tree, use Files.walk:
try (Stream<Path> tree =
Files.walk(Paths.get("/home/talha")).filter(Files::isReadable)) {
Iterator<Path> i = tree.iterator();
while (i.hasNext()) {
Path file = i.next();
try (Stream<String> lines = Files.lines(file, charset)) {
count += lines.filter(pattern.asPredicate()).count();
}
};
}
$PATH is an environment variable that tells the system where to search for executable programs (it's a list of directories separated by colons). It is usually set in your .bashrc or .cshrc file but this is only loaded when you log in. When Java runs, $PATH is likely not set because the rc file is not executed automatically, so the system can't find programs without specifying exactly where they are. Try using /bin/cat or /usr/bin/cat instead of just cat and see if it works. If it does, $PATH is your problem. You can add $PATH=/bin:/usr/bin to your script or just leave it with the directory name specified (e.g. /bin/cat).
Just because you can execute it in a login session doesn't mean it will work the same when a daemon like your Java program runs. You have to know what's in your .bashrc or .cshrc file and even sometimes how the system file is written (/etc/bashrc) in order to know how to write a script that runs under a daemon. Another consideration is that daemons often run under the context of a different user, and that throws things off, too.
I am trying to execute the C code from Java code which is already compiled and executed, but, I am not getting any output from the executable file. Can anyone help me to complete this task?
Code is as follows.
public class Test {
public static void main(String args[]) {
try {
Process processCompile = Runtime.getRuntime().exec("e:/Sample.exe");
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
Try this:
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(processCompile .getInputStream()));
// read the output from the command
System.out.println("EXE OUTPUT");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
This method would work only if you run the java program with admin privileges.
If you have privileges, then can you try running your process under "cmd" shell (Which is forked by your java process). An implementation do so this is done here "LinuxInteractor" ( But is in linux). Just minor change needed to port to Windows version.
Finding hard and soft open file limits from within jvm in linux (ulimit -n and ulimit -Hn)
I am creating a editor kind of application where I want to compile and run (of course create, edit, open also) C,C++ and Java files;
I am creating it in Java.
Now for compilation and running I am taking the whole path of file
and compiling & running via this full path.
for eg.
compileFileCommand = javac /media/disk/eclipse/\/UniversalIDE/Java/FirstJava.java
try
{
System.out.println("Compiling Java File");
Process compileProcess = Runtime.getRuntime().exec(compileFileCommand);
compileProcess.waitFor();
String line = "";
BufferedReader bri = new BufferedReader(new InputStreamReader(compileProcess.getInputStream()));
BufferedReader bre = new BufferedReader(new InputStreamReader(compileProcess.getErrorStream()));
while ((line = bri.readLine()) != null)
{
System.out.println(line);
}
bri.close();
while ((line = bre.readLine()) != null)
{
System.out.println(line);
}
bre.close();
compileProcess.waitFor();
System.out.println("Done Java Compile.");
} catch (Exception e)
{
// TODO: handle exception
System.out.println("Exception in Java Compile. ");
System.out.println(e.getMessage());
}
Above code works fine and create a class file at location of java file.But bri.readLine() always contains null.
For running Java file
runFileCommand = java /media/disk/eclipse/\/UniversalIDE/Java/FirstJava
And for running C & CPP files the same procedure
For C compilation
String compileFileCommand = "gcc " + fileNameWithFullPath;
For C Running
String runFileCommand = "./" + fileNameWithFullPath.split(".c")[0];
For CPP compilation
String compileFileCommand = "g++ " + fileNameWithFullPath;
For CPP Running
String runFileCommand = "./" + fileNameWithFullPath.split(".cpp")[0];
I use the same code as used for compiling java file but it does not give anything as result and bri.readLine() gives null all the time.
Please help me to solve this problem and please give me any suggestion on my application.
The default output filename from gcc and g++ is a.out, not input filename without extension.
Try runFileCommand = "./a.out", or use the -o option with gcc/g++ to specify output filename.
Also none of the compilation commands output anything when there's no errors or warnings.
bri.readLine() returns null because when a Java file compiles without error, nothing is printed to standard out. Was that the question?