I want to count the lines of file using java and the code that i use is:
String[] wcCommand = new String[]{"/usr/bin/wc","-l" , filePath};
Process wcProcess=Runtime.getRuntime().exec(wcCommand);
wcProcess.waitFor();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( wcProcess.getInputStream()));
String numberOfRowsline;
while((numberOfRowsline = bufferedReader.readLine()) != null) {
System.out.print(numberOfRowsline);
}
If i have large file with 5000000 rows then the command returns wrong number. Why this happens? When i execute the command direct from the terminal the returned value is correct.
The output from java is: 3288079 /PathToFile
The output from terminal: 5000000 /PathToFile
Related
I am running into some problems using ProcessBuilder, Process, and BufferedReaders in my Java program. For some inputs, the function runs perfectly but with others the BufferedReader reads nothing and returns empty strings. I am not sure what may be causing this bug.
I have tried debugging and for those situations where nothing is being read, the BufferedReader is completely skipping the loop. For example, when I pass in the command as 'ipconfig', which has >50 lines of CMD output, it returns every line exactly as displayed. But when I pass in the command as 'java -version', it completely skips the output (there are 3 lines that should be read).
ProcessBuilder/Reading function:
public static String runCommandToStdOut(String command) throws InterruptedException, IOException {
StringBuilder sBuilder = new StringBuilder();
pBuilder = new ProcessBuilder();
String[] processArray = command.split(" ");
pBuilder.command(processArray);
process = pBuilder.start();
process.waitFor();
BufferedReader bReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//reading cmd output to string
String line = "";
while ((line = bReader.readLine()) != null) {
sBuilder.append(line);
sBuilder.append(System.getProperty("line.separator"));
}
return sBuilder.toString();
}
How I am calling the function:
try {
String stdOut = osCommandService.runCommandToStdOut("java -version");
}
The stdOut string in the second code section is empty. That means the line 'sBuilder.toString' is an empty string after the function is run. The output that I see when I run 'java -version' directly in my cmd prompt is 3 lines long, which evidently isn't being read properly.
I am trying to run a linux command in java code. The command is raspivid which I have placed on the server under test.sh file for live camera streaming. Everything works fine but the problem is the streaming stops after some minutes after starting the tomcat server. Like the streaming stops after 6-7 minutes while running the command in java but at the background the raspivid process is running. On the other hand when I run the same command without using java code it works fine. Is this an issue of tomcat heap or anything else which stops the streaming? Please help see the below code:
try {
Process p = Runtime.getRuntime().exec(new String[]{"sudo","sh","/home/pi/test.sh"});
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
LOGGER.info("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
LOGGER.info(s);
}
// read any errors from the attempted command
LOGGER.info("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
LOGGER.info(s);
}
}
The problem is that BufferedReader.readLine() blocks until a full line (terminated by any line end char sequences) can be read, and you don't read the 2 outputs of the process "parallel", one if its buffer gets filled and the process gets blocked.
You need to read the data outputted by the process.
A process has 2 output streams: standard output and error output. You have to read both because the process might write to both of those outputs.
The output streams of the process have buffers. If the buffer of an output stream is filled, attempt to write further data to that by the process is blocked.
Do something like this:
BufferedReader stdInput = new BufferedReader(
new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(
new InputStreamReader(p.getErrorStream()));
while (p.isAlive()) {
while (stdInput.ready())
LOGGER.info(stdInput.readLine());
while (stdError.ready())
LOGGER.info(stdError.readLine());
Thread.sleep(1);
}
Problem with this solution (and fixing it):
This solution has an error. The process might not write full lines to its output. If that is the case, the process might still hang for example if it writes 1 character to its standard output then stdInput.readLine() would block (because it reads until a new line character is encountered) and if the process would keep writing to its error stream, when the buffer of the error stream is full, the process would be blocked.
So it would be better not to read the output streams of the buffer by lines but by characters (of course this makes logging it harder):
StringBuilder lineOut = new StringBuilder(); // std out buffer
StringBuilder lineErr = new StringBuilder(); // std err buffer
while (p.isAlive()) {
while (stdInput.ready()) {
// Append the character to a buffer or log if it is the line end
char c = (char) stdInput.read();
if (c == '\n') { // On UNIX systems line separator is one char: '\n'
LOGGER.info(lineOut.toString());
lineOut.setLength(0);
}
else
lineOut.append(c);
}
while (stdError.ready()) {
// Append the character to a buffer or log if it is the line end
char c = (char) stdError.read()
if (c == '\n') { // On UNIX systems line separator is one char: '\n'
LOGGER.info(lineErr.toString());
lineErr.setLength(0);
}
else
lineErr.append(c);
}
Thread.sleep(1);
}
Alternative (cleaner, more simple) solution
Alternatively you could start 2 threads, one to read the standard output of the process and one to read the standard error of the process. This could simplfy things:
private static void consumeStream(final InputStream is) {
new Thread() {
#Override
public void run() {
BufferedReader r = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = r.readLine()) != null)
LOGGER.info(line);
}
}.start();
}
And using it:
consumeStream(p.getInputStream());
consumeStream(p.getErrorStream());
I'm developing java application which allow to white or paste a source-code and run it without doing compiling procedure manually.what it do is save java code from text-box to a text-file and execute cmd command java java-file after execute javac java-file.file.
it's work fine but this problem came across when java file doesn't have any output .i mean if code create a swing form ..cmd haven't any output.then my java program get stuck actually i can't close it.i have to use external program to close it like taskmanager.
but when source-code has command-line output this problem never occurred .
OutputStream stdin = null;
BufferedReader br = null;
String line = null;
String command = null;
command = jTextField1.getText();
System.out.println(command);
Process p = Runtime.getRuntime().exec(command);
stdin = p.getOutputStream(); //use this to push commands
//processing stdout
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
// br.flush();
byte[] bytes = new byte[4096];
///////////////////////////////////////////
BufferedInputStream in = new BufferedInputStream(p.getInputStream());
while (in.read(bytes) != -1)
{
jTextArea1.append(br.readLine()+"\n");
}
///////////////////////////////////////////
For some terminal commands, they repeatedly output. For example, for something that's generating a file, it may output the percent that it is complete.
I know how to call terminal commands in Java using
Process p = Runtime.getRuntim().exec("command goes here");
but that doesn't give me a live feed of the current output of the command. How can I do this so that I can do a System.out.println() every 100 milliseconds, for example, to see what the most recent output of the process was.
You need to read InputStream from the process, here is an example:
Edit I modified the code as suggested here to receive the errStream with the stdInput
ProcessBuilder builder = new ProcessBuilder("command goes here");
builder.redirectErrorStream(true);
Process process = builder.start();
InputStream is = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
For debugging purpose, you can read the input as bytes instead of using readLine just in case that the process does not terminate messages with newLine
I need to get the hostId of my server using a Java program. Is there something in the Java API that is built-in which can help me do this?
lab.com$ hostid
f9y7777j -> How can I get this using java
The following would allow you to run a console command and store the result:-
ProcessBuilder pb = new ProcessBuilder("hostid");
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null)
{
// Store returned string here.
}
reader.close();
Try the following code:
System.out.println(java.net.InetAddress.getLocalHost().getHostName());