Reputation:
I am using the following code to run terminal commands through my command prompt
String[] command =
{
"zsh"
};
Process p = Runtime.getRuntime().exec(command);
new Thread(new SyncPipe(p.getErrorStream(), b)).start();
new Thread(new SyncPipe(p.getInputStream(), b)).start();
PrintWriter stdin = new PrintWriter(p.getOutputStream());
stdin.println("source ./taxenv/bin/activate");
stdin.println("python runner.py");
stdin.close();
int returnCode = 0;
try {
returnCode = p.waitFor();
String path2 = b + "/logs.txt"; // I am getting b value passed in from gc.jsp
if(new File(path2).exists())
{
BufferedReader reader = new BufferedReader(new FileReader(path2));
while ((line1 = reader.readLine()) != null)
{
content= content + line1 +"<br>";
}
reader.close();
request.setAttribute("logs", content);
RequestDispatcher rd = request.getRequestDispatcher("gc.jsp");
rd.forward(request, response);
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Return code = " + returnCode +b);
}
class SyncPipe implements Runnable
{
public SyncPipe(InputStream istrm, String c) {
istrm_ = istrm;
b_ = c;
}
@SuppressWarnings("unused")
public void run() {
try
{
final byte[] buffer = new byte[1024];
for(int length = 0; (length = istrm_.read(buffer)) != -1; )
{
str = str + IOUtils.toString(istrm_, "UTF-8") + b_;
}
System.out.println(str);
String location = b_ + "/" + "logs.txt";
File file = new File(location);
if(!file.exists())
{
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(str);
bw.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private final InputStream istrm_;
private final String b_;
When I run this code I expect it to be re directed to gc.jsp, but it displays as follows
Now, When I refresh the above page I am getting output as expected, shown below.
Why is this happening and how do I solve this?
=============================EDIT==========================
I've added
bw.close() //Closing bufferedwriter
fw.close() //Closing file writer
still of no use.
Now, I've added
TimeUnit.SECONDS.sleep(5);
This works fine for small files, so basically the problem is that code from the line
String path2 = b + "/logs.txt";
must wait for the process p to complete.
How do I do this?
Upvotes: 0
Views: 326
Reputation: 7994
Your problem is that you try reading the files before your SyncPipe
s finished writing to your files. You can solve this by waiting until all threads are finished (join()
)
Process p = Runtime.getRuntime().exec(command);
Thread threadError = new Thread(new SyncPipe(p.getErrorStream(), b));
Thread threadInput = new Thread(new SyncPipe(p.getInputStream(), b));
threadError.start();
threadInput.start();
/* writing to process */
// wait until your process finished
p.waitFor();
// wait for both threads until they finished writing to files
threadError.join();
threadInput.join();
// read your files
Description: Your SyncPipe thread will stop when the Input/ErrorStream is closed because the process p
stopped. Then it will write everything to file and close the files appropriately. After that the Thread is stopped correctly.
The join
method tells your main thread (the caller of join
) to wait until the thread is stopped (the callee of join, e.g. threadError). waitFor
is somewhat equivalent to join
.
After that you can say for sure that all threads are stopped correctly (p
, threadError
and threadInput
) and therefore all files are written to disk. Now you can read them.
Upvotes: 1