I am new to creating batch files. I followed a tutorial and wrote a program to redirect the output of an echo programs's simple Java version into the file test.txt. I am supposed to get output as:
E:\classes\com\javaworld\jpitfalls\article2>java GoodWinRedirect test.txt (Tutorials's example)
OUTPUT>'Hello World'
ExitValue: 0
Instead, when i type
C:\Users\attsuap1\Desktop\JavaCallingBatchFile2\src>GoodwinRedirect.java test.txt in my command prompt, a WordPad page opens, showing the codes that is in the java class.
If i type
C:\Users\attsuap1\Desktop\JavaCallingBatchFile2\src>java GoodWinRedirect test.txt,
I get the error:
Error: Could not find or load main class GoodWinRedirect
These are the codes:
GoodWinRedirect.java
import java.util.*;
import java.io.*;
class StreamGobbler extends Thread {
InputStream is;
String type;
OutputStream os;
StreamGobbler(InputStream is, String type) {
this(is, type, null);
}
StreamGobbler(InputStream is, String type, OutputStream redirect) {
this.is = is;
this.type = type;
this.os = redirect;
}
public void run() {
try {
PrintWriter pw = null;
if (os != null)
pw = new PrintWriter(os);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (pw != null)
pw.println(line);
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
public class GoodWinRedirect {
public static void main(String args[]) {
if (args.length < 1) {
System.out.println("USAGE java GoodWinRedirect <outputfile>");
System.exit(1);
}
try {
FileOutputStream fos = new FileOutputStream(args[0]);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World'");
// any error message?
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT", fos);
// kick them off
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
fos.flush();
fos.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
How do i get the output as OUTPUT>'Hello World' ExitValue: 0 in the command prompt? Someone please help me. Thank you so much in advance.
Related
The following batch script that works fine if I run it in a batch file (.bat). It gets all the files on the SFTP server and downloads to the local folder.
However, if I run this from the Java code, it gets only 4 files. Why is that it stops after it gets the 4 files?
Batch script:
winscp.com /log=C:\winscp\logs\winscp_detailed.log /xmllog=C:\winscp\logs\winscp.log /command ^
"open sftp://root:password#xx.xxx.xx.xx/ -privatekey=""C:\winscp\key.ppk"" -hostkey=""ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"" -passphrase=""password""" ^
"get /home/SFTP/* C:\LocalFolder1\" ^
"exit"
Java Code that executes the above command:
public HashMap runExternalProgram_Windows(String Command) {
String line;
InputStream stderr = null;
InputStream stdout = null;
HashMap _m = new HashMap();
try {
Process process = Runtime.getRuntime ().exec (Command);
Worker worker = new Worker(process);
worker.start();
try {
worker.join(30000);
if (worker.exit == null) {
throw new Exception();
}
} catch(Exception ex) {
_m.put("LOG_ERROR_EXTERNAL", "30 second time out...check connection");
ex.printStackTrace();
return _m;
} finally {
process.destroy();
}
stderr = process.getErrorStream ();
stdout = process.getInputStream ();
String _log_output = null;
// clean up if any output in stdout
BufferedReader brCleanUp = new BufferedReader (new InputStreamReader (stdout));
while ((line = brCleanUp.readLine ()) != null) {
if (_log_output==null) {
_log_output = line + "\n";
} else {
_log_output = _log_output + line + "\n";
}
}
brCleanUp.close();
_m.put("LOG_OUTPUT", _log_output);
String _log_error = null;
// clean up if any output in stderr
brCleanUp=new BufferedReader (new InputStreamReader (stderr));
while ((line = brCleanUp.readLine ()) != null) {
if (_log_error==null) {
_log_error = line + "\n";
} else {
_log_error = _log_error + line + "\n";
}
}
brCleanUp.close();
_m.put("LOG_ERROR_EXTERNAL", _log_error);
} catch (Exception e) {
//e.printStackTrace();
}
return _m;
}
private static class Worker extends Thread {
private final Process process;
private Integer exit;
private Worker(Process process) {
this.process = process;
}
public void run() {
try {
exit = new Integer(process.waitFor());
} catch (InterruptedException ignore) {
return;
}
}
}
For research reasons I want to be able to call the Scala REPL in my Java code. To do so I use Java's ProcessBuilder and call the command scala. Although the code nicely returns the welcome message of the scala REPL, the statements that I sent to it do not return any output or errors.
Note that my use of processbuilder is correct, I tested it on other commands and it works. It is specifically Scala that is not giving me any output or errors.
Why isn't Scala giving me any output? Is there a way to make it work?
Here is the short compilable version of my code:
public class CommandEvaluator {
public static void main(String args[]) throws IOException
{
ProcessBuilder pb = new ProcessBuilder("scala.bat");
Process proc = pb.start();
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERR");
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
OutputStream outStream = proc.getOutputStream();
PrintWriter pWriter = new PrintWriter(outStream);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) { // REPL
System.out.print("> ");
String stat = br.readLine();
pWriter.println(stat);
pWriter.flush();
}
}
private static class StreamGobbler extends Thread
{
private String type;
private BufferedReader br;
StreamGobbler(InputStream is, String type)
{
this.type = type;
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
}
#Override
public void run()
{
try
{
String line = null;
while ((line = br.readLine()) != null)
System.out.println(type + ">" + line);
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
I'm building a GUI with NetBeans, and one of the buttons in the GUI requires the use of a powershell script. I'm trying to get the script's output and put it into a JTextArea within the GUI. Here is what I have so far. I did a bit of debugging, and it seems to hang inside the while loop, but I'm confused as to why it's doing so.
private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("cmd powershell C:/hello1.ps1");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
outputTextArea.setText(line);
}
reader.close();
proc.getOutputStream().close();
} catch (IOException ex) {
Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
And here is a simple powershell script I'm trying to get it to work with.
#Filename: hello1.ps1
Write-Host "Hello World!"
#End of Script
I did some researched, and I noticed that it was hanging for other people to, but only because they forgot to close the processes output stream.
I was having the same issue. I moved the proc.getOutputStream().close() before the while loop and everything worked
private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
String allOutput = "";
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("cmd /c powershell C:/hello1.ps1");
BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
BufferedReader outReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = errorReader.readLine()) != null) {
allOutput += "\n" + line;
}
while ((line = outReader.readLine()) != null) {
allOutput += "\n" + line;
}
int retVal = proc.waitFor();
} catch (IOException ex) {
Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
}
outputTextArea.setText(allOutput);
}
Form the command line properly with CMD.EXE /c
Check the ErrorStream
Use Process.waitFor() read the java-docs for the Process class.
No need to close the OutputStream since you never use it and the program shouldn't expect user input (java switching the names of input and output is annoying)
NOTE the code above isn't tested, so there may be syntax errors etc etc.
Here is my tested code, note the choice to "hack" or close STDIN when done.
package test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Test
{
private static boolean hack=false;
public static void main(String[] args) throws IOException
{
Runtime rt = Runtime.getRuntime();
String cmd[];
if (hack)
cmd=new String[]{"cmd","/c","C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1", "<NUL"};
else
cmd=new String[]{"C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1"};
final Process p = rt.exec(cmd);
Thread stdout = new Thread()
{
public void run()
{
InputStream out = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(out));
String line = null;
try
{
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
};
};
stdout.start();
Thread stderr = new Thread()
{
public void run()
{
InputStream err = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(err));
String line = null;
try
{
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
};
};
stderr.start();
if (hack)
;
else
p.getOutputStream().close();
}
}
This helped me: Do not read the InputStream if there are no errors.
e.g.
private void takeAction () throws IOException, InterruptedException
{
String action = getAction (); // A powershell-Command
Process p = Runtime.getRuntime ().exec ( action );
InputStream is = p.getErrorStream ();
if ( 0 < is.available () )
{
BufferedReader br = new BufferedReader (
new InputStreamReader ( is ) );
String err = br.readLine ();
while ( null != err )
{
System.out.println ( "takeAction() " + err );
err = br.readLine ();
}
p.getOutputStream ().close ();
}
}
I want to write a Java program that runs an external "java myprog < input.txt > output.txt" command. The eventual goal is to run this command on two different programs and compare their output similarity from their respective output files.
I think I've read just about every relevant article about using ProcessBuilder to run an external program, and the few entries about handling user input in that external program, but I still can't get things working. From what I have read, I think the best approach is to not run the exact command above, but instead read the input.txt file and feed it byte-by-byte into the Process object, then collect the output and write it to output.txt ... I am 100% open to other options.
I put together the code below based on my readings. It seems to correctly feed input from input.txt into myprog, but when I try to print the external program's output to the console to verify, the program hangs at the point where (surprise) user input is expected in myprog.
I get the same issues with and without the redirectErrorStream(true) line.
I really want this to be in Java since I plan to share the source code with the people whose program outputs I will compare, and they are primarily only familiar with Java.
import java.io.*;
import java.util.*;
public class test7 {
public static void main(String args[]) {
try {
// WANT: "java myprog < input.txt > output.txt"
String inputFile = "input.txt";
String outputFile = "output.txt";
ProcessBuilder pb = new ProcessBuilder("java","myprog");
pb.redirectErrorStream(true); // merge stdout, stderr of process
Process p = pb.start();
// write input to the running program
OutputStream pos = p.getOutputStream();
InputStream fis = new FileInputStream(inputFile);
int read = 0;
while ( (read = fis.read()) != -1) {
pos.write(read);
}
fis.close();
// get output of running program
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
// HANGS HERE WHEN USER INPUT REQUIRED
String lineRead;
while ((lineRead = br.readLine()) != null) {
System.out.println(lineRead);
}
}
catch (IOException e) {
e.printStackTrace();
}
} // end main
}
Here is the content of myprog.java:
import java.io.*;
public class myprog {
public static void main(String args[]) throws IOException {
System.out.println("Hello world!");
System.out.println("Enter something:");
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
// the readLine() command causes ProcessBuilder to hang
cin.readLine();
}
}
And the input.txt file is just
p
The output.txt file should be
Hello world!
Enter something:
I wonder if your problem is partly to do with not using separate threads for reading input and writing output. For instance:
public static void main(String args[]) {
try {
// WANT: "java myprog < input.txt > output.txt"
String inputFile = "input.txt";
String outputFile = "output.txt";
// my ProcessBuilder Strings will be different from yours
ProcessBuilder pb = new ProcessBuilder("java", "-cp", ".;bin;",
"yr12.m04.a.MyProg");
pb.redirectErrorStream(true);
Process p = pb.start();
final OutputStream pos = p.getOutputStream();
final PrintWriter pw = new PrintWriter(pos);
final InputStream fis = new FileInputStream(inputFile);
final BufferedReader fileBr = new BufferedReader(new InputStreamReader(fis));
InputStreamReader isr = new InputStreamReader(p.getInputStream());
final BufferedReader br = new BufferedReader(isr);
new Thread(new Runnable() {
public void run() {
String lineRead;
try {
while ((lineRead = br.readLine()) != null) {
System.out.println(lineRead);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
try {
String lineRead;
while ((lineRead = fileBr.readLine()) != null) {
pw.println(lineRead);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (pw != null) {
pw.close();
}
if (fileBr != null) {
try {
fileBr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
} // end main
Have you thought about using Runtime.getRuntime().exec() instead?
Process proc = Runtime.getRuntime().exec("java myprog "+inputFile+" "+outputFile);
You could include the jar of the 'myprog' and call the main() method yourself. Even more so if myprog is in your domain you could get rid of the main method altogether.
I have the following code and I can't figure out why it won't work:
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
final String p1 = "HELLO WORLD";
process(p1, bos);
Assert.assertEquals("BOS value should be: "+p1, p1, bos.toString("UTF-8"));
It prints:
junit.framework.ComparisonFailure: BOS value should be: HELLO WORLD expected:<[HELLO WORLD]> but was:<[]>
at junit.framework.Assert.assertEquals(Assert.java:81) etc...
and process looks like this:
public static void process(final String p1, final OutputStream os) {
final Runtime rt = Runtime.getRuntime();
try {
final String command = "echo " + p1;
log.info("Executing Command: " + command);
final Process proc = rt.exec(command);
// gobble error and output
StreamGobbler.go(proc.getErrorStream(), null);
StreamGobbler.go(proc.getInputStream(), os);
// wait for the exit
try {
final int exitVal = proc.waitFor();
log.info("Command Exit Code: " + exitVal);
} catch (InterruptedException e) {
log.error("Interrupted while waiting for command to execute", e);
}
} catch (IOException e) {
log.error("IO Exception while executing command", e);
}
}
private static class StreamGobbler extends Thread {
private final InputStream is;
private final OutputStream os;
private static StreamGobbler go(InputStream is, OutputStream os) {
final StreamGobbler gob = new StreamGobbler(is, os);
gob.start();
return gob;
}
private StreamGobbler(InputStream is, OutputStream os) {
this.is = is;
this.os = os;
}
public void run() {
try {
final PrintWriter pw = ((os == null) ? null : new PrintWriter(os));
final InputStreamReader isr = new InputStreamReader(is);
final BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (pw != null) {
pw.println(line);
}
log.info(line); // Prints HELLO WORLD to log
}
if (pw != null) {
pw.flush();
}
} catch (IOException ioe) {
log.error("IO error while globbing", ioe);
}
}
When I run the jUnit test I get an empty string as the actual. I don't understand why this wont work.
EDIT: I am using RHEL5 and eclipse 3.6 if that makes a difference at all.
maybe you should wait on the thread filling the stream:
Thread thr = StreamGobbler.go(proc.getInputStream(), os);
// wait for the exit
try {
final int exitVal = proc.waitFor();
log.info("Command Exit Code: " + exitVal);
thr.join();//waits for the gobbler that processes the stdout of the process
} catch (InterruptedException e) {
log.error("Interrupted while waiting for command to execute", e);
}