Are there any programming defects in this Java code? - java

import java.lang.*;
import java.io.*;
class test
{
public static void main(String[] a) throws Exception
{
int i;
String[] str = new String[]{"javac","example.java"};
String[] str1 = new String[]{"java","example"};
Runtime r = Runtime.getRuntime();
Process p = null;
Process p1 = null;
p=r.exec(str);
p1=r.exec(str1);
InputStreamReader reader = new InputStreamReader (p1.getInputStream ());
BufferedReader br = new BufferedReader(reader);
FileWriter fw = new FileWriter("this.txt",true);
char[] c = new char[1];
while ((i=br.read())!=-1)
{
c[0] = (char) i ;
fw.write(c);
c = new char[1];
}
fw.close();
}
}
this a simple program using runtime class.
is there any termination of 'process' code need to be employed?
Thanks in advance!!!

1 . There's no reason to initialize the process objects to null.
Just do:
Process p = r.exec(str);
Process p1 = r.exec(str1);
While you're at it, better variable names would help
2 . You can improve performance by reading and writing more than 1 character at a time:
3 . You may want to explicitly specify encodings, rather than using the platform default.
InputStreamReader reader = new InputStreamReader (p1.getInputStream (), inputCharsetName);
BufferedReader br = new BufferedReader(reader);
FileOutputStream fos = new FileOutputStream("this.txt", true);
Writer writer = new OutputStreamWriter(fos, outputCharsetName);

The input stream is never closed, and I recommend closing the writer in a finally block.

You should use Process.waitFor() in order to let the compiling process complete. Otherwise you will likely try to run a non-existing class file because compilation took too long.
The buffer is too small, everytime you do something like char[] c = new char[1]; // lolz array with exactly one element you should look at least twice.

Your program will not work the way as you would expect it to. ie. it will try to run the example.class before even the compilation of example.java is completed.

is there any termination of 'process' code need to be employed?
I think that depends on the processes - will they terminate on their own? (And do you want them to terminate when this program does?)
You can terminate easily with:
p.destroy();
p1.destroy();

First, you need to wait for the compilation to complete before executing the second process. Use the waitFor() method:
int compilationResult = -1;
try {
compilationresult = p.waitFor();
}
catch (InterruptedException ie) {
...
}
Then check compilationResult (a value of 0 indicates successful compilation) to determine whether to continue with the rest of the code.
Secondly, if you're finished with the p1 process after processing its output, then you should either wait for it to finish, or kill it yourself - depending on whether you expect the process to complete by itself or not.
To wait for the process to complete normally, use a similar block of code to above, by enclosing p1.waitFor() in a try/catch block.
To kill it yourself, use:
p1.destroy();
After you're sure the process has completed, you might then want to check the exit value with p1.exitValue(). Why be so careful about this? Well, you probably shouldn't trust the output you're collecting and writing to this.txt until you're sure the process executed correctly.

Related

How to use a regular expression to parse a text file and write the result on another file in Java

I used a regular expression to parse a text file to use the resulted group one and two as follows:
write group two in another file
make its name to be group one
Unfortunately, No data is written on the file!
I did not figure out where is the problem, here is my code:
package javaapplication5;
import java.io.*;
import java.util.regex.*;
public class JavaApplication5 {
public static void main(String[] args) {
// TODO code application logic here
try {
FileInputStream fstream = new FileInputStream("C:/Users/Welcome/Desktop/End-End-Delay.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
File newFile1= new File("C:/Users/Welcome/Desktop/AUV1.txt");
FileOutputStream fos1= new FileOutputStream(newFile1);
BufferedWriter bw1= new BufferedWriter(new OutputStreamWriter(fos1));
String strLine;
while ((strLine = br.readLine()) != null) {
Pattern p = Pattern.compile("sender\\sid:\\s(\\d+).*?End-End\\sDelay:(\\d+(?:\\.\\d+)?)");
Matcher m = p.matcher(strLine);
while (m.find()) {
String b = m.group(1);
String c = m.group(2);
int i = Integer.valueOf(b);
if(i==0){
System.out.println(b);
bw1.write(c);
bw1.newLine();
}
System.out.println(b);
// System.out.println(c);
}
}
}
catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
Can anyone here help me to solve this problem and Identify it?
You are using BufferedWriter, and never flush (flushing writer pushes the contents on disk) your writer or even close it at the end of your program.
Due to which, before your content gets written in actual file on disk from BufferedWriter, the program exits and the contents get lost.
To avoid this, either you can call flush just after writing contents in bw1,
bw1.write(c);
bw1.newLine();
bw1.flush();
OR
Before your program ends, you should call,
bw1.close(); // this ensures all content in buffered writer gets push to disk before jvm exists
Calling flush every time you write the data is not really recommended, as it defeats the purpose of buffered writing.
So best is to close the buffered writer object. You can do it in two ways,
Try-with-resources
Manually close the buffered writer object in the end, likely in the finally block so as to ensure it gets called.
Besides all this, you need to ensure that your regex matches and your condition,
if(i==0){
gets executed else code that is writing data in file won't get executed and of course in that case no write will happen in file.
Also, it is strongly recommended to close any of the resources you open like file resources, database (Connection, Statements, ResultSets) resources etc.
Hope that helps.

ProcessBuilder BufferedReader read() blocking

I'm using ProcessBuilder to run a command line tool we are using. During its run the tool asks 2 yes/no questions, so usually I answer 'y' twice and then press enter after each time. My problem is that the tool always finishes its run when running from cmd, but when I run it through my java code, it sometimes work and sometimes gets stuck on while ((n = op.read(buffer)) != -1) (with the same input).
Here is my code. Am I doing something wrong? What am I missing? Thanks.
List<String> processArgs = new ArrayList<>();
processArgs.add(0, "java");
processArgs.add(1, "-jar");
processArgs.add(2, JAR_PATH);
processArgs.add(3, "-put");
processArgs.addAll(args);
try
{
// run tool with put
ProcessBuilder pb = new ProcessBuilder(processArgs);
pb.directory(new File("src\\temp"));
pb.redirectErrorStream(true);
Process p = pb.start();
// write 'y' to the tool's stdin.
String answer = "y" + System.getProperty("line.separator");
// yes to first question
p.getOutputStream().write(answer.getBytes());
p.getOutputStream().flush();
// read tool's process stdout
this.op = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringWriter sw = new StringWriter();
int n = 0;
boolean answered = false;
char[] buffer = new char[BUFFER_SIZE];
while ((n = op.read(buffer)) != -1)
{
sw.write(buffer, 0, n);
if (sw.toString().contains("second question") && !answered)
{
// yes to second question
p.getOutputStream().write(answer.getBytes());
p.getOutputStream().flush();
answered = true;
}
}
stdout = sw.toString();
exitCode = p.waitFor();
}
catch (IOException | InterruptedException e)
{
throw new ToolException("process had an exception:\n" + e.getMessage());
}
UPDATE:
I changed my code and added pb.redirectErrorStream(true), but now the process still gets blocked on op.read(buffer). When I debug it seems that it's stuck on the second question, even though I wrote 'y' twice to the output stream. Am I using getOutputStream() incorrectly?
SECOND UPDATE:
The second question didn't get the second 'y' as an answer, and it caused the process to wait for input. I changed the code so i will show the proper way to insert input to the subprocess outputstream.
The output and error stream are buffered. When the buffer fills up the program stops waiting for you to read it. However you only read the output first so if the error stream fills you have a deadlock.
A simple solution is to redirect the error to the output so you have only one stream to read. i.e.
pb.redirectErrorStream(true);
As per the documentation https://docs.oracle.com/javase/8/docs/api/java/lang/ProcessBuilder.html
Alternatives include; writing error to a file, or reading it in another thread.

Multiple stdin Terminal Inputs from an ArrayList Using BufferedWriter

Trying to take an ArrayList and input all its Strings into a command line program, then grab the output. I'm only able to go one time through the loop, before the streams are closed and I cannot use them anymore (java IOException Stream Closed). I have to close the streams, because otherwise I can't get the output from the program for a given input that comes from the ArrayList. Is there any way around this?
ProcessBuilder pb = new ProcessBuilder(cmd);
Process p = pb.start();
BufferedReader stdout = new BufferedReader( new InputStreamReader(p.getInputStream()) );
BufferedWriter stdin = new BufferedWriter( new OutputStreamWriter(p.getOutputStream()) );
for(String sequence : editedSequences){
stdout.write(sequence);
stdout.close();
String line = "";
line = stdin.readLine();
while ((line = stdin.readLine()) != null) {
structure += line;
}
stdin.close();
System.out.println("seq: " + sequence);
System.out.println("struc: " + structure);
structure = structure.substring(0, sequence.length());
System.out.println("struc: " + structure);
sequenceStructurePair = new String[]{sequence, structure};
sequenceStructurePairs.add(sequenceStructurePair);
}
Dont close the streams. Instead, flush the input stream after writing to it (stdin.flush()).
The fix here was I simply added everything I had outside the for loop to the inside of the for loop. I assume for someone (very) particularly concerned with speed that this would be a potentially problematic approach, but I'm more concerned with this working -- I don't care, for example, if a large file takes 5-10 minutes longer to process as a result of constantly having to discard and make new objects.
I definitely want to hear from more people, though. Again, I can't remove the .close() on the BufferedWriter without causing the program to hang.

Reading InputStream from Java Interactive Process using ProcessBuilder

I am trying to run an interactive executable from Java application using ProcessBuilder; it's supposed to take input, produce output and then wait for the next input. The main problem here with Input/Output streams. I send an input and get nothing. Here is the code:
private static Process process;
private static BufferedReader result;
private static PrintWriter input;
process = new ProcessBuilder("compile-lm", lmFile.toString(), " --score yes").redirectErrorStream(true).start();
input = new PrintWriter(new OutputStreamWriter(process.getOutputStream()), true);
input.println(message);
System.out.println(message);
result = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = new String();
while ((line = result.readLine()) != null)
{
/* Some processing for the read line */
System.out.println("output:\t" + line);
}
I have tried your code it works fine there is no problem with the code. I think that the problem with the command that you are trying to execute ( it returns nothing ). try to change parameters or even change the entire command to test. and if you can execute the comand in other place ( terminal for example try it and see the output with the same parameters )
I have used a similar setup many times over but can not find a working copy right now :( My first instinct though is to move the line where you initialise the reader (result variable) to before the one where you send the command out to the process (input.println(message)).
Try closing the output stream to the process. Basically you're at the mercy of whatever buffering is happening in the output side of the child process.

Communicating with C++ process from Java

First, I saw a few Q's about this issue in the site, but didn't see any answer that solve my problem.
I have a program written in Java and it calls a cmd program written in C++. (this is an assumption since I don't have the actual source) I know the expected I/O of the C++ program, in the cmd it is two lines of output and then it waits for string input.
I know that the first output line of the program is through error stream, and I receive it properly (this is expected), but I don't get the second line in error or input stream.
I tried to write to the program right after the first line ( the error line) and didn't got stuck, but there was no response.
I tried using 3 different threads, for each stream, but again, nothing was received in input/error stream after the first line, and the program didn't respond to writing through output stream.
My initializers are:
Process p = Runtime.getRuntime().exec("c:\\my_prog.exe");
BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
Is it possible at all or maybe it depends on the C++ program?
Thanks,
Binyamin
If you want to call native applications like C and C++ from Java, you need to use JNI.
I would suggest to put the input in the program when it has started, it will propably use that as input when it wants it.
Here is how I execute any command line in Java. This command line may execute any program:
private String executionCommandLine(final String cmd) {
StringBuilder returnContent = new StringBuilder();
Process pr;
try {
Runtime rt = Runtime.getRuntime();
pr = rt.exec(cmd);
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = null;
while ((line = input.readLine()) != null) {
returnContent.append(line);
}
input.close();
LOG.debug(returnContent.toString());
// return the exit code
pr.waitFor();
} catch (IOException e) {
LOG.error(e.getMessage());
returnContent = new StringBuilder();
} catch (InterruptedException e) {
LOG.error(e.getMessage());
returnContent = new StringBuilder();
}
return returnContent.toString();
}

Categories

Resources