Writing command line output to a file with in Java - java

I am running a command line command from java:
ping localhost > output.txt
The command is send via a Java like this:
Process pr = rt.exec(command);
For some reason the file is not created, but when i run this command from the
command line itself, the file does create and the output is in that file.
Why doesn't the java command create the file?

Because you haven't directed it to a file.
On the command line, you've requested that it be redirected to a file. You have to do the same thing in Java, via the InputStream provided by the Process object (which corresponds to the output stream of the actual process).
Here's how you get the output from the process.
InputStream in = new BufferedInputStream( pr.getInputStream());
You can read from this until EOF, and write the output to a file. If you don't want this thread to block, read and write from another thread.
InputStream in = new BufferedInputStream( pr.getInputStream());
OutputStream out = new BufferedOutputStream( new FileOutputStream( "output.txt" ));
int cnt;
byte[] buffer = new byte[1024];
while ( (cnt = in.read(buffer)) != -1) {
out.write(buffer, 0, cnt );
}

1. After successfully executing the command from Java program, you need to read the output, and then divert the Output to the file.
Eg:
Process p = Runtime.getRuntime().exec("Your_Command");
InputStream i = p.getInputStream();
InputStreamReader isr = new InputStreamReader(i);
BufferedReader br = new BufferedReader(isr);
File f = new File("d:\\my.txt");
FileWriter fw = new FileWriter(f); // for appending use (f,true)
BufferedWriter bw = new BufferedWriter(fw);
while((br.readLine())!=null){
bw.write(br.readLine()); // You can also use append.
}

Complementing Andy's answer, I think you MUST read this article: http://www.javaworld.com/jw-12-2000/jw-1229-traps.html.
It is very important for who needs to deal with external processes in Java.

I you want to keep it simple, and you are using Windows, try:
Process pr = rt.exec("cmd /c \"ping localhost > output.txt\"");

Related

Is there any way command prompt error logs can be stored somewhere?

I have ran a java jar file in command prompt. For suppose the program execution fails with some error, I want the errors to be logged somewhere so that I can check later.
Is there any way this can be achieved?
You can use a command > output.txt to store the command line output into a separate file.
java -jar application.jar > output.txt
you can use location custom location for output.txt as well.
java -jar application.jar > D:\\myfolder\\output.txt
or you can create a java program to run external jar application using Runtime.getRuntime().exec() which helps you manipulate the output to display and perform actions according to the output.
Process myProcess = Runtime.getRuntime().exec("java -jar application.jar");
BufferedReader reader = new BufferedReader(new InputStreamReader(myProcess.getInputStream()));
while ((consoleOutput = reader.readLine()) != null) {
saveLogs(consoleOutput);
System.out.println(consoleOutput);
}
myProcess.waitFor();
InputStream in = myProcess.getInputStream();
InputStream err = myProcess.getErrorStream();
byte[] b = new byte[in.available()];
in.read(b, 0, b.length);
saveLogs(consoleOutput);
System.out.println(new String(b));
byte[] c = new byte[err.available()];
err.read(c, 0, c.length);
saveLogs(consoleOutput);
System.out.println(new String(c));
Use FileWriter to save the consoleOutput into a file.
public void saveLogs(String text) {
try (FileWriter f = new FileWriter("log\\output.log", true);
BufferedWriter b = new BufferedWriter(f);
PrintWriter p = new PrintWriter(b);) {
p.println(text);
} catch (IOException ex) {
logger.error("SAVE_LOGS_ERROR", ex);
}
}
I think logback is what you are looking for (http://logback.qos.ch/index.html).
It helps you to config the log level (infor , debug, error, ...) and the location of the log file.

How do I make my program run and interact with shell program?

There is a program I run in Ubuntu terminal, called ProgramABC, which reads a query until user presses CTRL+D, and then writes some data to the standard output. It works perfectly:
/path/ProgramABC >> file.txt [enter]
<here I write my query> [enter]
<and I press CTRL+D>
<data is written to file.txt and ProgramABC closes automatically>
I want to run it from Java. My code doesn't work - it creates the file.txt, but it's empty, so I guess something is wrong with passing my query to the process, and therefore to ProgramABC. What do I do wrong? Here is a part of my code:
ProcessBuilder builder = new ProcessBuilder("bash","-c","/path/program ABC >> file.txt");
builder.directory(new File("/another/path/"));
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write("<my query here>");
writer.write((char)4); //it's CTRL+D, right?
writer.flush();
writer.close();

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.

java shell command to sort csv file

i need to sort a csv file by the first column, which is a timestamp. I've been trying to do this with the following code, but the inputstream of the process p is always just blank:
Process p = Runtime.getRuntime().exec("sort -k1,1 -t, Bucket_Stats.csv");
p.waitFor();
// read this file into InputStream
InputStream in = p.getInputStream();
OutputStream output = new FileOutputStream("Sorted_Bucket_Stats.csv");
System.out.println(IOUtils.copy(in,output));
output.flush();
output.close();
Instead of handling the output in Java, you can use the
-o or --output=FILE
flag of the sort command and pass a filename for the output.
If you pass the same filename as the input, it will be overwritten.

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");

Categories

Resources