How to get command prompt output in java? - java

How to get the output of the command prompt which means i have opend a command prompt like this.
Process process = Runtime.getRuntime().exec("cmd /c start cmd.exe /K \"C:\\Editor\\editorTemp.exe\"");
i can not get the cmd output like this
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
So how can i get the command prompt output ?

This is not Java question. Basically what you doing is running Java (Java Main Process A) and from it starting another process (Windows CMD B). This is fine and you can get input/output streams of this process (B) in Java(A).
However this process (B) starts another process (again Windows CMD C) with its own standard input/output. This process has nothing common with processes A&B and uses Windows' standard Input/Output streams. So, there are no connections between A and C.
I'm not sure but I think there are some ways to run Windows CMD with different or not standard IO. Maybe something like this will work:
cmd <tty >tty
but there is no tty in Windows. Pragmatically you can do this as described here - Creating a Child Process with Redirected Input and Output but that would not work for regular CMD.
Nevertheless it became even more problematic when you start your own process from the editorTemp.exe (process D). D has even more disconnection with process A. And all for what? What don't you simply start process D directly from A and have full control on the IO streams and process itself?
Here is good example how to do so.

Your java thread is working independently of CMD call. The java code is beating the STDOUT pipe before anything is written.
If you call Process.waitFor(), it will wait until the CMD call is done. The STDOUT should be in the buffer, and then you can read it.

When you do a readLine(), your java thread is blocked until you have an actual full line or the input stream is closed.
If the program prints a partial line (without CR or LF at the end), and then waits for input, the readLine will be stuck.
So you will need to read character by character, until you think the proces has no more things to say.
See e.g. Is it possible to read from a InputStream with a timeout?

import java.util.Scanner;
Inside the main write this.
Scanner output = new Scanner(System.in);
System.out.println(“Enter your name”);
String name = output.next();
If you want user to enter an int then you need to do this.
int number = output.nextInt();

Related

How to stop an input-waiting Windows batch process in Java?

I have a Windows batch file simple.bat which produces some output in stdin, and ends with a pause. I want to run this batch file and then process the output in my Java code.
// create a Java process with simple.bat
Process p = Runtime.getRuntime().exec("cmd /c simple.bat");
// get the output from the process p
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
The problem with the above code is that simple.bat ends with a pause and that makes p still hanging in there waiting for the key to be pressed. As a result, eventually reader.readLine() will be blocked and never returns.
Unfortunately, simple.bat is passed on to me as-is. I cannot remove the pause line.
I can add
Thread.sleep(1000);
p.destroy();
after the exec("cmd /c start simple.bat") line to terminate the process p before processing its output. What if the batch file is run on slow machine? I am seeking advice is there a better way then asynchronously stopping the process. Thank you very much!!
If your script doesn't require any input sent to it, and you are running it as cmd /c simple.bat, then the simplest thing to do is to close the process's standard input:
p.getOutputStream().close();
I ran a quick test myself, and this dismissed the pause and let the script terminate. You will of course have the extra line Press any key to continue . . . in your output, but I imagine you can deal with that.
Destroying the process can be correct as a fallback. You will have to think about how you would prefer your application to fail: is aborting to soon worse than a hanging process? Which of the failures will the user actually notice?
In most cases both of the above are undesirable.
If you know you have reached the pause (based on the last readline()), you can actually write to the process. This can be done by getting an output stream Process.getOutputStream(). I haven't been able to test this, but normally pause should also react to characters written this stream.

Getting too many arguments error while executing tr command from java

file = D:\Unix\tr.exe "Æ" "~" < "C:\SourceFiles\source.csv" > "D:\tgt"
When i execute this command using the below code in java
Process process = Runtime.getRuntime().exec(file);
am getting the following error
D:\Unix\tr.exe: too many arguments
PS : File contains Æ characters am trying to replace all those characters with ~
Any suggestions please ?
You're passing unicode in the CMD, I guess that causes the problem.
Set chcp xxx on the CMD and try.
refer below link for chcp codes
https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/chcp.mspx?mfr=true
You have to program the io redirection yourself. This is usually the bash that takes care of it.
The result of the exec() call is a process. This process can then be used to get the STDIN of the process. Send the data to that process using that stream.
The way you call it, you send another command line option to tr, which is the < and > redirectors and the filenames.
Process process = System.getRuntime().exec(strBatchFileName);
OutputStream stdin = process.getOutputStream();
sendFileToStream(out);
InputStream stdout = process.getInputStream();
loadResultFromStream(stdout);
This is a pseudocode example, where sendFileToStream(...) feeds the input file into the TR process, and the loadResultFromStream(...) will load the result.
You may need to utilize threads to feed and read if the data is larger than the stream's buffer.
The question is kind of a duplicate and you will find a ProcessBuilder example here: Runtime's exec() method is not redirecting the output

Executing a WMIC command line argument in Java

I'm trying to use the WMIC command 'DESKTOP' in an application through a method which is implemented from an interface. Before using WMIC commands in cmd, it's necessary to first input 'WMIC' and press enter, as I'm sure you all know. I can do this just fine, however after the command line enters WMIC mode, I need to subsequently enter the DESKTOP command, or any other WMIC command (see list : http://ss64.com/nt/wmic.html). Here's the overridden method code I'm currently using to enter WMIC mode :
#Override
public void Desktop(){
try {
Runtime rt = Runtime.getRuntime();
String cmd = "cmd /c WMIC";
Process pr = rt.exec(cmd);
}
Perhaps I'm going about this the wrong way? Any help would be much appreciated.
You need to get the output stream of the process you started and write to it.
OutputStream os = pr.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("DESKTOP");
bw.newLine();
bw.flush();
If you need to see the output/errors from the process you started you need to use getInputStream() and getErrorStream() methods to get the output/error streams and read from it.
Check the javadoc of Process for more details.
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
Pay special attention to this part -
By default, the created subprocess does not have its own terminal or
console. All its standard I/O (i.e. stdin, stdout, stderr) operations
will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods getOutputStream(),
getInputStream(), and getErrorStream(). The parent process uses these
streams to feed input to and get output from the subprocess. Because
some native platforms only provide limited buffer size for standard
input and output streams, failure to promptly write the input stream
or read the output stream of the subprocess may cause the subprocess
to block, or even deadlock.
It's a fairly silly answer.
WMIC is normally used in non interactive mode.
wmic desktop get
However you are a programmer. Therefore you are supposed to program.
Here's vbs script that does it. The help is filled with sample scripts in C, VB, VBS, and JScript.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Desktop")
For Each objItem in colItems
msgbox objItem.Name & " " & objItem.Wallpaper
Next

shell script to redirect the output

I am looking for a help regarding a shell script to redirect the output of a command to a file. I have a C program that reads the input from a serial port and display. I want this data to be redirected to a file. I am executing this from a java program by calling
Runtime r = Runtime.getRuntime();
Process procObj = r.exec("sh " + scriptfile);
I have tried writing the script file as
./program >> file.txt
The file.txt is not getting updated. Here, the program doesn't end until the connection to the port is lost, in a sense it is infinitely running. So my program keeps looking for data on the port and display as and when it is there.
I just need to redirect the same output to a file that I would use as a log.
I looked at How to make shell output redirect (>) write while script is still running? but not helpful.
Kindly help..
How much output does program generate? Using standard IO redirection will add a 4KB buffer between stdout and file. This means your program must output more than 4KB of data before the OS starts to write to the file.
To fix this, add stdout.flush() to your program when a "work unit" is complete (maybe a line but might be more than one line).
Can you try ./program >> file.txt 2>>file.txt, or ./program 2>&1 >>file.txt?
just try this
List<String> cmd = new ArrayList<String>();
cmd.add("sh");
cmd.add("-c");
cmd.add("program 1> file.txt 2>&1");
ProcessBuilder pb = new ProcessBuilder(cmd);
Process p = pb.start();
If you use standard C calls for output (printf, puts etc.), your output may get buffered. On C89 and onwards, it depends on the buffering mode (unbuffered, fully buffered, line buffered) and on the size of the buffer, whether your output is buffered at all and when the buffer is flushed (see http://www.gnu.org/software/libc/manual/html_node/Buffering-Concepts.html and man setvbuf).
By default, output to a file is fully buffered on Linux. If you want the output to appear immediately in the output file, you may:
use fflush() after each output operation
use the system call write() (man 2 write)
switch off buffering: setvbuf(stdout, NULL, _IONBF, 0); (https://stackoverflow.com/a/7876756/601203)
This behaviour is not related on the fact the you start your C program in a Java program via a shell script. This behaviour depends on the standard C library that you have linked into your program.

Runtime.exec not running the "find" command

My problem is that, i am using Runtime.getruntime.exec() function to run my unix command on Java. But, it jumps to the end of codes while exec() command is being run. The codes are below.
Process songProcess;
ArrayList<String> xmlFilePathsForEmi = new ArrayList<String>();
int countForEmiSongUpdates = 0;
String line;
try {
songProcess = Runtime.getRuntime().exec(new String[]{"find /home/gozenem/emiornek/ -name '*.xml'"}); // It jumps here !
songProcess.waitFor();
bufferedReaderSong = new BufferedReader(new InputStreamReader(songProcess.getInputStream()));
while((line = bufferedReaderSong.readLine()) != null){
xmlFilePathsForEmi.add(line);
}
...
...
...
}
I do not know what it is related to, may be there is a character that exec function could not run. I need your precious help. Thank you.
Your String[] parameter to Runtime.exec() is incorrect. It must be split up so that it contains one element per item (the executable must be one string, then each individual argument must come in its own string).
Try something like:
songProcess = Runtime.getRuntime().exec(new String[]{"find", "/home/gozenem/emiornek/", "-name", "*.xml"});
Also calling waitFor where you are doing isn't appropriate. You need to read the output while the process is running, otherwise you risk filling up the I/O buffers that are used between the Java VM and your process. So move that waitFor to after you've processed the output.
From the Process docs:
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, [...]. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

Categories