Using Java's process builder to call a C program - java

Trying to call a C program using Java's process builder but don't know what to call in the process builder call.
Process p = new ProcessBuilder("myCommand", "myArg").start();
For myCommand and myArg, what values would I replace it with for it to run a C Program? The program I want it to call is shown here:
calculator.c:
#include <stdio.h>
int main ()
{
int a = 4;
int b = 2;
int c = a + b;
printf("Result: %d \n", c);
}

If calculator.c has not been compiled yet, you will want to first compile it:
Process compile = new ProcessBuilder("gcc", "calculator.c").start();
Process execute = new ProcessBuilder("./a.out").start();
Any relevant compiler flags (e.g., -O or -o calculator) should be included in the arguments as well. If you do rename the executable, you'll want to change ./a.out with it.
A better way (in terms of having few hard-coded constants) would be to have some variables like:
String c_file = "calculator.c";
String output_exe = "calculator";
Process compile = new ProcessBuilder("gcc", "-o " + output_exe, c_file).start();
Process execute = new ProcessBuilder("./" + output_exe);
Lastly, you'll probably want to make sure each of your processes are exiting without error:
if (compile.getInputStream().read() == -1) {
// that means something was written to stderr, and you can do something like
System.out.error("ERROR!");
System.exit(-1);
}
As #VinayDandekar pointed out, you can also do this with exitValue.
if (compile.exitValue() == -1) {
// that means something was written to stderr, and you can do something like
System.out.error("ERROR!");
System.exit(-1);
}

At First Set Your Compiler Path On Environment Variable From Windows System Property Otherwise It will not work . Then Set Compile And Run Code
Compile Code: `
JFileChooser fileChooser=new JFileChooser();
if (fileChooser.showSaveDialog(compile.this) != JFileChooser.APPROVE_OPTION)
return;
File file = fileChooser.getSelectedFile();
try {
FileWriter out = new FileWriter(file);
textEditor.write(out);
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
String filepath = file.getPath();
String filepath2 = filepath.substring(0, filepath.lastIndexOf(File.separator));
System.out.println(filepath);
System.out.println(filepath2);
String name = file.getName();
String name2 = file.getName().substring(0, file.getName().lastIndexOf("."));
String folder = filepath2+"\\";
String exe = folder+name2+".exe";
System.out.println(exe);
ProcessBuilder pb=new ProcessBuilder();
try {
pb = new ProcessBuilder("cmd", "/C", "gcc " + "\"" + filepath2 + "\\" + name + "\"" + " -o \"" + name2+"\"");
pb = new ProcessBuilder("cmd", "/C", "g++ " + "\"" + filepath2 + "\\" + name + "\"" + " -o \"" + name2+"\"");
pb.directory(new File(filepath2));
Process p = pb.start();
p.waitFor();
int x = p.exitValue();
if (x == 0) {
area.setForeground(red);
area.setText(" == 0 error.. Compilation Finished");
} else {
BufferedReader r = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//BufferedWriter rm=new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
String out;
area.setText("");
while ((out = r.readLine()) != null)
{
area.setForeground(RED);
area.append(out + System.getProperty("line.separator"));
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
`
Run Code: `
JFileChooser fileChooser=new JFileChooser();
if (fileChooser.showSaveDialog(compile.this) != JFileChooser.APPROVE_OPTION)
return;
File file = fileChooser.getSelectedFile();
try {
FileWriter out = new FileWriter(file);
textEditor.write(out);
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
String filepath = file.getPath();
String filepath2 = filepath.substring(0, filepath.lastIndexOf(File.separator));
System.out.println(filepath);
System.out.println(filepath2);
String name = file.getName();
String name2 = file.getName().substring(0, file.getName().lastIndexOf("."));
String folder = filepath2+"\\";
String exe = folder+name2+".exe";
System.out.println(exe);
ProcessBuilder pb=new ProcessBuilder();
try {
pb = new ProcessBuilder("cmd", "/C", "gcc " + "\"" + filepath2 + "\\" + name + "\"" + " -o \"" + name2+"\"");
pb = new ProcessBuilder("cmd", "/C", "g++ " + "\"" + filepath2 + "\\" + name + "\"" + " -o \"" + name2+"\"");
pb.directory(new File(filepath2));
Process p = pb.start();
p.waitFor();
int x = p.exitValue();
int z=p.exitValue();
if (x == 0) {
Runtime rt = Runtime.getRuntime();
try {
String username = System.getProperty("user.name");
String c = "#echo off\n" + "\"" +
filepath2 + "\\" + name2 + ".exe\"\n" + "echo.\n" + "echo.\n" + "echo Process Terminated\n" +
"pause\n" +
"exit";
File dir = new File("C:\\Users\\" + username + "\\CodeEditor");
dir.mkdir();
try {
File file2 = new File("C:\\Users\\" + username + "\\CodeEditor" + "\\run.bat");
file2.createNewFile();
PrintWriter writer = new PrintWriter(file2);
writer.println(c);
writer.close();
Process p2 = Runtime.getRuntime().exec("cmd /c start run.bat", null, new File("C:\\Users\\" + username + "\\CodeEditor"));
} catch (Exception ex) {
}
} catch (Exception ex) {
}
} else {
JOptionPane.showMessageDialog(compile.this, "Compilation Error", "Error", JOptionPane.ERROR_MESSAGE);
}
} catch (Exception ex) {
ex.printStackTrace();
}
`
Done!!!

Runtime can be used to execute any command line instruction supported by OS.
Example below would be of help.
package com.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class CommandExec {
public static void main(String[] args) {
try {
Process pr = Runtime.getRuntime().exec("ls /etc");
BufferedReader read = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String str = read.readLine();
while (str != null){
System.out.println(str);
str = read.readLine();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Related

Lag from BufferedReader

I am having trouble finding the source of lag in my code. I believe I have narrowed the possible source down to this method.
Essentially I start a script, set it in a Process variable p, and grab the output from the script using a BufferedReader, and put it into an ArrayList.
Somehow I am getting lag when the script outputs (it outputs at a 5 minute interval)
Any ideas?
public void runCommand(String path)
{
if (SystemUtils.IS_OS_WINDOWS)
{
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "cd " + path + " && " + this.getCommand());
builder.redirectErrorStream(true);
try
{
p = builder.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
else
{
try
{
String name = ManagementFactory.getRuntimeMXBean().getName();
String pid = name.substring(0, name.indexOf("#"));
p = Runtime.getRuntime().exec("./btrace.sh " + pid + " " + path + " " + this.getConfig().getPort());
}
catch (Exception e)
{
e.printStackTrace();
}
}
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
try
{
// Print out everything that's happening.
while (true)
{
line = r.readLine();
if (line == null)
{
break;
}
if (this.isDebugEnabled)
{
System.out.println("[Script Output]: " + line);
}
lines.add(line);
}
r.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
Seems like I found the cause of lag.
After researching how ArrayLists resize, I realized it could be performance taxing and tried using a Linked list.
So far seems like the issue is fixed.
Thanks!

calling program from another program using bat file

I have a problem, i want to run my program with another program with a parameter. in first program, this is the code:
public static void main(String[] args) {
System.out.println("Starting cmd main");
String runPath = args[0];
String path = args[1];
String flagname = args[2];
String lockPath = args[3];
String tampung = args[4];
String command = "cmd.exe "
+ "/C"
+ " cd C:\\Program Files\\WinRAR"
+" && rar a -n "+runPath+tampung+".zip "
+ path+ flagname + " -p"+tampung
+ "\n && rar a -n "+lockPath+tampung+".zip "
+ path+ flagname + " -p"+tampung;
try {
Runtime.getRuntime().exec(command);
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
when i try to run in cmd, the program i compiled without any errors. But when i try to call from another program, the program is running but the Runtime not give any result. Here the second program:
public static void main(String[] args) {
String runPath = "E:\\Sementara\\DEVELOPMENT\\SpoolPFileLapBulTBEListener\\FLAG\\RUN\\";
String path = "E:\\Sementara\\DEVELOPMENT\\SpoolPFileLapBulTBEListener\\FLAG\\";
String flagname = "CMDcommand.txt";
String lockPath ="E:\\Sementara\\DEVELOPMENT\\SpoolPFileLapBulTBEListener\\FLAG\\RUN\\LOCK\\";
String tampung = "testing";
String cmd = "C:\\ProgramCmd\\Start.bat" + " " + runPath + " " + path + " "+ flagname + " " + lockPath + " " + tampung;
String[] command = { "cmd.exe", "/c", cmd };
System.out.println("Command: " + cmd);
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line="";
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
process.waitFor();
} catch (IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
For the .bat in the first program, i use this:
java CmdMain %1 %2 %3 %4 %5
When i try to running the program, here the result:
Command: C:\ProgramCmd\Start.bat E:\Sementara\DEVELOPMENT\SpoolPFileLapBulTBEListener\FLAG\RUN\ E:\Sementara\DEVELOPMENT\SpoolPFileLapBulTBEListener\FLAG\ CMDcommand.txt E:\Sementara\DEVELOPMENT\SpoolPFileLapBulTBEListener\FLAG\RUN\LOCK\ testing
C:\Users\Agung Rizkiono\Documents\Development\Workspace2\testing2>java CmdMain E:\Sementara\DEVELOPMENT\SpoolPFileLapBulTBEListener\FLAG\RUN\ E:\Sementara\DEVELOPMENT\SpoolPFileLapBulTBEListener\FLAG\ CMDcommand.txt E:\Sementara\DEVELOPMENT\SpoolPFileLapBulTBEListener\FLAG\RUN\LOCK\ testing
How can i try to fix the second program?

Unix count line of file command - from java code

I'm trying to count the number of lines of a text file using a unix command from java code.
My code looks like:
String filePath = "/dir1/testFile.txt";
Runtime rt = Runtime.getRuntime();
Process p;
try {
System.out.println("No: of lines : ");
findLineCount = "cat " + filePath + " | wc -l";
p = rt.exec(findLineCount);
p.waitFor();
} catch (Exception e) {
//code
}
But, nothing is displayed in the console. When I execute the command directly, it works. What could be the issue in the above code?
I suggest you use a ProcessBuilder instead of Runtime.exec. You can also simplify your command by passing the filePath to wc. Please don't swallow Exception(s). Finally, you can use ProcessBuilder.inheritIO() (Sets the source and destination for subprocess standard I/O to be the same as those of the current Java process) like
String filePath = "/dir1/testFile.txt";
try {
System.out.println("No: of lines : ");
ProcessBuilder pb = new ProcessBuilder("wc", "-l", filePath);
pb.inheritIO();
Process p = pb.start();
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
Of course, it's more efficient to count the lines in Java without spawning a new process. Perhaps like,
int count = 0;
String filePath = "/dir1/testFile.txt";
try (Scanner sc = new Scanner(new File(filePath));) {
while (sc.hasNextLine()) {
String line = sc.nextLine();
count++;
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.printf("No: of lines : %d%n", count);
When I execute the command directly
I doubt you're execute it "directly". You're probably running it in a shell.
Your code should run that script in a shell too.
rt.exec(new String[]("bash", "-c", findLineCount});
This is how i printed number of lines
public static void main(String[] args) {
try {
Runtime run = Runtime.getRuntime();
String[] env = new String[] { "path=%PATH%;" + "your shell path " }; //path of cigwin bin or any similar application. this is needed only for windows
Process proc = run.exec(new String[] { "bash.exe", "-c", "wc -l < yourfile" }, env);
BufferedReader reader = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
String s;
while ((s = reader.readLine()) != null) {
System.out.println("Number of lines " + s);
}
proc.waitFor();
int exitValue = proc.exitValue();
System.out.println("Status {}" + exitValue);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}

How to execute command line from Java with setting the variables

try {
String command = "java -Xms64m -Xmx512m -cp %mypath% com.app.GenericAxlTool -i " + ip + " -v 6.0 -a " + axlVer + " -d " + dbVer + " -u " + userName + " -p " + password + " -c sqlselect -f " + queryFile;
String[] envArr = {pathCmd};
System.out.println("Command is: " + command);
ProcessBuilder pb = new ProcessBuilder(command);
Map<String, String> env = pb.environment();
env.put("mypath", ".;lib/gatui.jar;lib/gat.jar;lib/swing-layout-1.0.jar;lib/smtp.jar;lib/AbsoluteLayout.jar;lib/axis.jar;lib/commons-discovery-0.2.jar;lib/jaxm-runtime.jar;lib/jaxrpc.jar;lib/saaj-api.jar;lib/saaj-impl.jar;lib/activation.jar;lib/JSAP-2.1.jar;lib/SNMP4J.jar;lib/mailapi.jar;lib/jtapi.jar;lib/remotehands.jar;lib/conftransfer.jar;lib/jtapi.jar;;lib/devicedashboard.jar;lib/pcdb.jar;lib/lic.jar;lib/poi-3.8-20120326.jar");
pb.directory(new File(curDir));
Process p = pb.start();
//Runtime runtime = Runtime.getRuntime();
//Process p = runtime.exec(command, envArr, new File(curDir));
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
System.out.println("Done with: " + queryFile);
} catch (IOException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
return false;
}
The above code results in IOException and secondly, I dont get any output from the stream as well. Here is folder structure.
MainDir
|
--lib
--src
|
--com.query.Exec
|
javafile.java
I dont know what are you trying to do with your code, but to execute commandlines you can simply use
Runtime.getRuntime().exec(command)
where command is a string representing the command you want to run.

Database restoring with java code - program not responding

I'm trying to restore a backed up .sql file using Java program. I'm posting the method below. But when I execute this the program halts for a long time. Then I executed same mysql command in command line(Windows) it's works charmingly.
Puzzled where I missed. What do you think ?
File file;
final JFileChooser fc = new JFileChooser();
int returnVal = fc.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
try {
System.out.println(file.getCanonicalPath());
String executeCmd = "mysql -u " + username + " -p" + password +" " + dbName+" < "+" \" "+file.getCanonicalPath()+"\" " ;
Process runtimeProcess;
runtimeProcess = Runtime.getRuntime().exec(executeCmd);
int processComplete = runtimeProcess.waitFor();
if (processComplete == 0) {
JOptionPane.showMessageDialog(Interface.mainFrame, "Database Backup restored successfully.", "Netmetering", 1);
} else {
System.out.println("Could not restore the backup");
}
} catch (IOException | InterruptedException ex) {}
...
String executeCmd = "mysql -u " + username + " -p" + password +" " + dbName+" < "+" \" "+file.getCanonicalPath()+"\" " ;
Process runtimeProcess = Runtime.getRuntime().exec(executeCmd);
InputStream is = runtimeProcess.getInputStream();
// Do one OR the other, but not both ;)
// If you don't care about the output, but I think it's a bit of waste personally...
while (is.read() != -1) {}
// I'd at least dump the output to the console...
int byteRead = -1;
while ((byteRead = is.read()) != -1) {
System.out.print((char)byteRead );
}
int processComplete = runtimeProcess.waitFor();
if (processComplete == 0) {...}
I would also recommend using ProcessBuilder over creating the Process manually like this, it handles the parameters better - IMHO
In general the correct way to run an external program is:
build you external program command line
build the ProcessBuilder and Process
build your own StreamRender
execute your external program
check the STDOUT and STDERR of your external program
verify the exit status of your external program
you can achieve this sequence as described following:
String command = "mysql -u... -p... dbname < file.sql";
ProcessBuilder pb = new ProcessBuilder(command);
Process pr;
try {
pr = pb.start();
StreamRender outputStdout = new StreamRender(pr.getInputStream(), StreamRender.STDOUT);
// your STDOUT output here
outputStdout.start();
StreamRender outputStderr = new StreamRender(pr.getErrorStream(), StreamRender.STDERR);
// your STDERR outpu here
outputStderr.start();
pr.waitFor();
if (pr.exitValue() != 0) {
// your external program fails
} else {
// ok, your external program was executed correctly
}
} catch (Exception e) {
// ...
} finally {
// ...
}
StreamRender.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class StreamRender extends Thread {
public static final String STDOUT = "STDOUT";
public static final String STDERR = "STDERR";
private InputStream inputStream;
private String inputType;
public StreamRender(InputStream inputStream, String inputType) {
this.inputStream = inputStream;
this.inputType = inputType;
}
public void run() {
try {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(inputStreamReader);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(this.inputType + " > " + line);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}

Categories