Unable to run and give input to C code through Java - java

I want to run a C code through Java to print an integer which is entered by the user. I'm using ProcessBuilder class.
The Java code gives the same output (stdout:0) for every integer that I input through outputstream.
public class test {
public static void main(String args[]) throws IOException {
String line;
ProcessBuilder builder = new ProcessBuilder("first1.exe");
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
InputStream err=process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write(8);
writer.flush();
line = reader.readLine();
System.out.println("Stdout: " + line);
}
}
I always get the output:
stdout:0
The C code for first1.exe is:
#include <stdio.h>
int main ()
{
int n;
scanf("%d",&n);
printf("%d",n);
return 0;
}

use
process.waitFor();
writer.write(8+"\n");
enter code here

In the above code when the C code first1.exe executes, it waits for an input to be given.
Here the writer just writes 8 and does nothing while the code first1.exe requires the user to write 8 and press enter.
The above code does not work because enter or newline is not given.
Replacing the line writer.write(8); with writer.write(8+"\n"); and add process.waitFor() before writer.write(8+"\n") and it will work properly.
On replacing the statement, the code gives stdout:8 as output.

Related

Why does BufferedReader fail if BufferedWriter is still open?

I am trying to run a .exe file from a java application and would like to be able to use it (for now) like a terminal where i can write to the .exe then read back from it before writing it again.
My issue is that the code only works when the writer is closed before the reader attempts to read from the inputstream.
String line = "", prev = "";
Scanner scan = new Scanner(System.in);
ProcessBuilder b = new ProcessBuilder("myexe");
b.redirectErrorStream(true);
Process p = b.start();
OutputStream stdin = p.getOutputStream();
InputStream stdout = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
System.out.println ("->");
while (scan.hasNext()) {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
String input = scan.nextLine();
if (input.trim().equals("exit")) {
writer.write("C");
} else {
writer.write(input);
}
writer.flush();
//writer.close();
while ((line = reader.readLine ()) != null) {
System.out.println ("[Stdout] " + line);
if (line.equals(prev)){
break;
}
prev = line;
}
reader.close();
}
So my question is, am i doing something wrong with the ProcessBuilder? I have read about not reading the output correctly can cause the system to hang. But this doesnt explain why it hangs when the writer is still open?
The issue was actually with my C compiled .exe. When it was running, the application was printing an output, therefore working in cmd terminal however i had not flushed the buffer after each command sent. Once i had done this, the java application would recognise each command as they were sent.

C Program at runtime to execute the shell with respect to the input and output In JAVA

import java.io.*;
import java.util.Scanner;
public class runtime {
public static void main ( String [] args) {
try {
Process proc= Runtime.getRuntime().exec("bash -c " + "./a.out" );
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedWriter stdOutput = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
String s = "";
BufferedReader reader = new BufferedReader((new InputStreamReader(System.in)));
String sendMemo = reader.readLine();
stdOutput.write(sendMemo+"\n");
stdOutput.flush();
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
}
catch( IOException e ) { System.out.println ( e )};
}
}
C code
#include<stdio.h>
int main()
{
int a;
printf("InPUt : \n");
scanf("%d",&a);
printf("std : %d",a);
}
I want to execute C Program In JAVA. I think to use this shell Command from JAVA:
runtime.getRuntime().exec
So i want result this:
print :: Input : <-value input 5
print ::std : 5
but
my code is
value input 5
print :: Input :
print :: std : 5
help me please
Your Java program reads "5" from standard input, which is dutifully echoed, since standard input is the terminal.
Then, you are passing this to the called C program's standard input via a pipe. This pipe isn't the terminal any more, so there's no echo; the line containing "5" is read without echo, and processed. So you'll see the prompt ("InPUt"), but no echo.

Running an interactive shellscript using java

I am writing a javacode to call a interactive shellscript and using process builder for calling shellscript. I know that to pass parameters to this shell script i have to take its inputstream to check it's output and need to use output stream to pass command to it. My question is that how would I know using Input Stream that it's prompting for entering values ?
My code :
ProcessBuilder pb2=new ProcessBuilder("/home/abhijeet/sample1.sh","--ip="+formobj.getUpFile().getFileName(),"--seqs="+seqs);
script_exec = pb2.start();
OutputStream in = script_exec.getOutputStream();
InputStreamReader rd=new InputStreamReader(script_exec.getInputStream());
pb2.redirectError();
BufferedReader reader1 =new BufferedReader(new InputStreamReader(script_exec.getInputStream()));
StringBuffer out=new StringBuffer();
String output_line = "";
while ((output_line = reader1.readLine())!= null)
{
out=out.append(output_line+"/n");
System.out.println("val of output_line"+output_line);
//---> i need code here to check that whether script is prompting for taking input ,so i can pass it values using output stream
}
Is there any way to know directly that script is waiting for an input from user?
Read the process output stream and check for the input prompt, if you know the input prompt, then put the values to process inupt stream.
Otherwise you have no way to check.
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
BufferedReader b1 = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter w1 = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
String line = "";
String outp = "";
while ((line = b1.readLine()) != null) {
if (line.equals("PLEASE INPUT THE VALUE:")) {
// output to stream
w1.write("42");
}
outp += line + "\n";
}
...
UPD: for your code it should be something like that
ProcessBuilder pb2=new ProcessBuilder("/home/ahijeet/sample1.sh","--ip="+formobj.getUpFile().getFileName(),"--seqs="+seqs);
script_exec = pb2.start();
OutputStream in = script_exec.getOutputStream();
InputStreamReader rd=new InputStreamReader(script_exec.getInputStream());
pb2.redirectError();
BufferedReader reader1 =new BufferedReader(new InputStreamReader(script_exec.getInputStream()));
StringBuffer out=new StringBuffer();
String output_line = "";
while ((output_line = reader1.readLine())!= null)
{
out=out.append(output_line+"/n");
System.out.println("val of output_line"+output_line);
//---> i need code here to check that whether script is prompting for taking input ,so i can pass it values using output stream
if (output_line.equals("PLEASE INPUT THE VALUE:")) {
// output to stream
in.write("42");
}
}

Executing Shell Scripts from Java, Shell scripts having read operation

I have a Shell Scripts that read the Input
#!/bin/bash
echo "Type the year that you want to check (4 digits), followed by [ENTER]:"
read year
echo $year
I'm executing this shell scripts using JAVA APi
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "/junk/leaptest.sh");
final Process process = pb.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Program terminated!");
In the Java Console I can see the Output
Type the year that you want to check (4 digits), followed by [ENTER]:
Now the Actual Problem in How to pass the values to the Shell Scripts in my scripts how the varialble "year" can be read
I have edited the code as per the suggestion but doesn't work where we correct it
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "/junk/leaptest.sh");
final Process process = pb.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
/*
* OutputStream os = process.getOutputStream(); PrintWriter pw = new
* PrintWriter(os);
*/
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
while ((line = br.readLine()) != null) {
System.out.println(line);
// pw.println("8999");
bw.write("2012");
}
System.out.println("Program terminated!");
You can use the OutputStream of the Process class:
OutputStream os = process.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println("1997");
What you write to this output stream will become the input stream of the shell script. So read year will read 1987 to the year variable.
EDIT:
I also tried it out and I've managed to find the problem. The 1997 string hasn't reached the script, beacuse PrintWriter buffers the data that was written to it. You either have to flush the PrintWriter stream after the println() with pw.flush() or you have to set the auto-flush property to true upon creation:
PrintWriter pw = new PrintWriter(os, true);
Here is the complete code that was working fine for me:
leaptest.sh:
#!/bin/bash
echo "Type the year that you want to check (4 digits), followed by [ENTER]:"
read year
echo $year
Test.java:
import java.io.*;
class Test {
public static void main(String[] args) {
try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "leaptest.sh");
final Process process = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
PrintWriter pw = new PrintWriter(process.getOutputStream());
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
pw.println("1997");
pw.flush();
}
System.out.println("Program terminated!");
} catch(Exception e) {
e.printStackTrace();
}
}
}
Output:
$ java Test
Type the year that you want to check (4 digits), followed by [ENTER]:
1997
Program terminated!
To pass values from java program that executes script to the script use command line arguments. If you want to send information back from script to java program print the value in script, read the script's STDOUT in java program and parse it.
You really almost there. Now you are reading the script output (into while loop) but you are just printing it. Parse the output and do what you need with it.
Think you should parse input stream is to extract your values. Parse it by lines.
You want to set up an OutputStream using getOutputStream aswell, to be able to write data from your Java program into the process.
public abstract OutputStream getOutputStream()
Gets the output stream of the subprocess. Output to the stream is piped into the standard input stream of the process represented by
this Process object.
I think this should work. You need to handle your subprocess' output stream. Read the docs.
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
bw.write("2012");

Using Runtime.getRuntime().exec in eclipse

I'm using Runtime.getRuntime().exec in eclipse to run another java program from the current program.
I've used the following code.
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
System.out.println("Enter the class name");
String s=br.readLine();
String str="XYZ";
String[] cmd = {"java","-cp", "C:/Users/..../workspace/Testing/bin",s,str};
Process pro=Runtime.getRuntime().exec(cmd);
I'm also passing a string "XYZ" to that program. That program just accepts the string and displays
Your string is XYZ
But by using the line
String[] cmd = {"java","-cp",
"C:/Users/..../workspace/Testing/bin",s,str};
i'm able to run the program but it is not accepting any arguments. It is neither displaying the output nor showing any errors.
Where am i going wrong?
Consider the program to be called is
import java.io.*;
public class Test
{
public static void main(String[] args) throws IOException
{
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
System.out.println("Enter any string");
String s=br.readLine();
System.out.println("Your string is "+s);
}
}
This program should accept the string XYZ and prints Your string is XYZ
You need to read the output (and error) streams from the Process using getInputStream() and getErrorStream(). You’ll need a separate thread for this if you want to wait for the process to complete.
String[] cmd = {"java", "-cp", "C:/Users/..../workspace/Testing/bin", s, str};
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
final InputStream pOut = p.getInputStream();
Thread outputDrainer = new Thread()
{
public void run()
{
try
{
int c;
do
{
c = pOut.read();
if (c >= 0)
System.out.print((char)c);
}
while (c >= 0);
}
catch (IOException e)
{
e.printStackTrace();
}
}
};
outputDrainer.start();
p.waitFor();
If you are using Java 7 and want all output of the process to be redirected to the console, the code is considerably simpler:
String[] cmd = {"java", "-cp", "C:/Users/..../workspace/Testing/bin", s, str};
Process p = new ProcessBuilder(cmd).redirectError(Redirect.INHERIT)
.redirectOutput(Redirect.INHERIT)
.start();
p.waitFor();
The redirectError() and redirectOutput() methods with Redirect.INHERIT cause output to just be sent to the parent Java process.
You are executing javac, the language compiler. I believe you want to invoke the java runtime on the class file with your main method. Replace javac with java, and specify your main class.
You are passing your data as an Argument but reading it from System.in. If you read the data from the arguments it'll work. So do what #prunge said to capture what the subprocess print and use this as your test and everything will work just fine.
import java.io.*;
public class Test
{
public static void main(String[] args) throws IOException
{
if(args.length==0)
System.out.println("No String received");
else
System.out.println("Your string is " + args[0]);
}
}
Be sure that you check both the InputStream and the ErrorStream.
If you however want to pass the data via System.in then you have to change your call code to:
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
System.out.println("Enter the class name");
String s=br.readLine();
String str="XYZ";
String[] cmd = {"java","-cp", "C:/Users/..../workspace/Testing/bin",s};
Process pro=Runtime.getRuntime().exec(cmd);
PrintWriter output= new PrintWriter(pro.getOutputStream());
output.println(str);

Categories

Resources