I have been trying to invoke a Python 3.x program from Java. What I need is to get output from python and write it to a file. This is what I have done. This is creating a Json file but does not gives the output. Please help me out here.
public static void main(String[] args) throws ScriptException, IOException {
Process p = Runtime.getRuntime().exec("python <path to the file>/reg.py");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String ret = in.readLine();
System.out.println(ret);
BufferedWriter out = new BufferedWriter(new FileWriter("<some path>/output.json"));
out.write(ret);
out.close();
}
Ok, so after our talk in the comments, your script throws an error because it cannot find a file output.txt. Now, the thing is that this is logged to an error stream not the regular one. What you should do is to open that stream and read it:
BufferedReader in = new BufferedReader(new InputStreamReader(p.getErrorStream()));
In fact, you could open both streams: errorStream and outputStream and read error stream first to check if it contains something (it means that execution failed). If it doesn't, open outputStream and read its contents normally.
Related
public static void executeCommand(String cmd) {
try {
Process process = Runtime.getRuntime().exec(cmd, null,
new File("/usr/hadoop-0.20.2/"));
InputStream stdin = process.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.println("<output></output>");
while ((line = br.readLine()) != null)
System.out.println(line);
InputStreamReader esr = new InputStreamReader(
process.getErrorStream());
BufferedReader errorReader = new BufferedReader(esr);
String lineError;
while ((lineError = errorReader.readLine()) != null)
System.out.println(lineError);
process.waitFor();
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
Here's my code for executing a command named 'cmd'. But I cannot get realtime output through this code. The output comes out when the command finishes. I want realtime output. Is there a way to do this?
The issue you describe is most likely caused by the application you called: many applications use unbuffered I/O when connected to a terminal, but bufferen I/O when connected to a pipe. So your cmd may simply decide not to write its output in small bits, but instead in huge chunks. The proper fix is to adjust the command, to flush its output at the appropriate times. There is little you can do about this on the Java side. See also this answer.
I think you need to have a thread for handling the output.
You should try first with the cmd which run for a while
Last time, when I try with wvdial command (this wvdial will not finish until we stop it), I need a thread to read the output of wvdial
Actually, the problem is that Process.getInputStream() returns a BufferedReader.
So, even if the called subprocess flushes all its output, a read in the calling Java program will only get it if the buffer is full.
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");
I'm making application which needs to read strings from file on FTP Server. I use apache.commons.net.FTPClient for it. I have following code:
Log.e("sizzeee", String.valueOf(mClient.listFiles().length));
InputStream stream=mClient.retrieveFileStream(f.getName());
DataInputStream in=new DataInputStream(stream);
BufferedReader buf=new BufferedReader(new InputStreamReader(in));
List<String> tasks=new ArrayList<String>();
String s;
while ((s=buf.readLine())!=null) {
tasks.add(s.trim());
}
stream.close();
in.close();
buf.close();
Log.e("sizzeee", String.valueOf(mClient.listFiles().length));
That works correctly, but I have some problems: last Log instruction shows "0" files in current directory! But first Log instruction shows "6" files. Therefore I think that I don't close file stream or something else. Please, inform me about my mistake. Thank you
I have a program to pull the source code of a webpage and save it to a .txt file. It works if done with just one at a time, but when I go through a loop of say 100 pages all of a sudden each page source starts to get cut off between 1/4 and 3/4 of the way through (seems to be arbitrary). Any ideas on why or how I would go about solving this?
Initial thoughts where that the loop is going too fast for the java (I am running this java from a php script) but then thought that it technically shouldn't be going to the next item until the current condition was finished anyway.
Here is the code I'm using:
import java.io.*;
import java.net.URL;
public class selectout {
public static BufferedReader read(String url) throws Exception{
return new BufferedReader(
new InputStreamReader(
new URL(url).openStream()));}
public static void main (String[] args) throws Exception{
BufferedReader reader = read(args[0]);
String line = reader.readLine();
String thenum = args[1];
FileWriter fstream = new FileWriter(thenum+".txt");
BufferedWriter out = new BufferedWriter(fstream);
while (line != null) {
out.write(line);
out.newLine();
//System.out.println(line);
line = reader.readLine(); }}
}
The PHP is a basic mysql_query while(fetch_assoc) grab the url from the database, then run system("java -jar crawl.jar $url $filename");
Then, it fopen and fread the new file, and finally saves the source to database (after escaping_strings and such).
You need to close your output streams after you finish writing each file. After your while loop, call out.close(); and fstream.close();
You must flush the stream and close it.
finally{ //Error handling ignored in my example
fstream.flush();
fstream.close();
}
I need to start external executable in such way that user can interact with program that was just started.
For example in OpenSuse Linux there is a package manager - Zypper. You can start zypper in command mode and give commands like install, update, remove, etc. to it.
I would like to run it from Java code in a way user could interact with it: input commands and see output and errors of the program he started.
Here is a Java code I tried to use:
public static void main(String[] args) throws IOException, InterruptedException {
Process proc = java.lang.Runtime.getRuntime().exec("zypper shell");
InputStream stderr = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
char ch;
while ( (ch = (char)br.read()) != -1)
System.out.print(ch);
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
}
But unfortunately I can only see it's output:
zypper>
but no matter what I write, my input doesn't affect program that was started.
How can I do what want to?
You need to get an output stream in order to write to the process:
OutputStream out = proc.getOuptutStream();
This output stream is piped into the standard input stream of the process, so you can just write to it (perhaps you want to wrap it in a PrintWriter first) and the data will be sent to the process' stdin.
Note that it might also be convenient to get the error stream (proc.getErrorStream) in order to read any error output that the process writes to its stderr.
API reference:
http://download.oracle.com/javase/6/docs/api/java/lang/Process.html
Seems like the converting inside the while condition fails in your example, this seems to work better (I don't run Suse so I haven't tried with Zypper):
public static void main(String[] args) throws IOException, InterruptedException
{
//Process proc = java.lang.Runtime.getRuntime().exec("zypper shell");
Process proc = java.lang.Runtime.getRuntime().exec("ping -t localhost");
InputStream stderr = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
int i;
while ( (i = br.read()) != -1)
{
System.out.print((char) i);
}
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
}
I recently wrapped Google Closure Compiler into a .jar-file which is extracted and used in a Process. This compiler only talks via System.in/out/err. There's a big "gotcha" in connecting pipes together, which is just briefly mentioned in the Process javadoc.
"...failure to promptly write the
input stream or read the output stream
of the subprocess may cause the
subprocess to block, and even
deadlock."
On Mac OS X the buffer is 16k, and if you don't read it promptly as suggested, the process deadlocks. My only solution to this problem ATM, is a rather nasty busy wait.
https://github.com/algesten/googccwrap/blob/master/src/main/java/googccwrap/GoogleClosureCompilerWrapper.java