I am developing a swing application in which I am running a cmd command using Runtime.getRuntime.execute(); and reading the output of command using BufferReader. Now what I want is I want to show the output in dialog with changing the text(Using JTextPane) inside it or appended strings in a textarea with the output of command like we can see while starting Eclipse of any other IDE for loading prerequisites.
I tried making subclass of JDialog class but it is not doing what i want.
My Code :
Process p = Runtime.getRuntime().exec(commandToBeExecuted);
BufferedReader in = new BufferedReader(newInputStreamReader(p.getInputStream()));
String line = null;
MessageDialog myDialog=new MessageDialog(UserInterface.this);
while ((line = in.readLine()) != null) {
System.out.println(line);
myDialog.setText(line);
myDialog.setVisible(true);
myDialog.setLocationRelativeTo(UserInterface.this);
}
} catch (Exception ex) {
Logger.getLogger(UserInterface.class.getName()).log(Level.SEVERE, null, ex);
errorGlobal.setText("Some Exception Occured in update "+ex.getMessage());
System.out.println("Exception occured " + ex.getMessage());
}
Is it possible to do what I want and what will be the best way to achieve this ?
Your problem is in the loop. Use JTextArea.append and put the rest outside the loop,
Related
I am trying to make it so that when a user clicks a button, a new screen appears and automatically runs a command line process, and they are able to see the outputs of this process.
I thought that I might be able to use a JTextArea to set text to.
Here's what I've got at the moment:
runButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent r)
{
JFrame runFrame = new JFrame("Running process...");
runFrame.setVisible(true);
runFrame.setSize(500, 400);
runFrame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
runFrame.setLayout(null);
JTextArea run = new JTextArea();
run.setBounds(100,50,300,200);
runFrame.add(run);
Runtime runtime = Runtime.getRuntime();
Process process = null;
try
{
process = runtime.exec("cat /cmd/h:/testfile");
}
catch (IOException e)
{
e.printStackTrace();
}
InputStream runStream = process.getInputStream();
InputStreamReader runStreamReader = new InputStreamReader(runStream);
BufferedReader br = new BufferedReader(runStreamReader);
String line;
StringBuilder sb = new StringBuilder();
try
{
while ((line = br.readLine()) != null)
{
sb.append(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
run.setText(sb.toString());
}
});
The error I'm getting with this is:
Cannot run program "cat": CreateProcess error=2, The system cannot find the file specified
I was trying to test opening a file to test this, which just contains lines of random letters.
EDIT:
I'm not sure I explained clearly what I need this to do.
What I want is for a command to be run in command line that opens a file. I then want the result of the command line to be output into the JTextArea.
EDIT 2:
I have tried to change my command to "ping riot.de -t". This will ping riots server every so often and it returns a response with the response time.
Upon running this, the new frame is just black, and java freezes up.
maybe the env of your java application execution has not the right path of cat cmd? you have try to specify absolute path for cat command?
Sorry guys maybe it can be a silly question but really i couldn't find any similar situation like this.
Here is my code:
private void startHashingButtonActionPerformed(java.awt.event.ActionEvent evt) {
consoleArea.setText( myFile.getName() + " started to be hashing! It can take few minutes, please wait.."); //20:05
try {
BufferedReader reader = new BufferedReader(new FileReader(myFile));
myHash = new HashOA(300000);
try {
while(reader.readLine() != null){
myHash.hash(reader.readLine());
}
consoleArea.append("\n" + myFile.getName() + " is successfully hashed!!");
} catch (IOException ex) {
Logger.getLogger(MainScreen.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(MainScreen.class.getName()).log(Level.SEVERE, null, ex);
}
}
I expect that in consoleArea(TextArea) there should be "file.txt started to be hashing! It can take few minutes, please wait.." written and after that the hashing process(that while(reader.readLine() != null) loop) should be started. But when i run the program and click on "startHashingButton" it first finishes hashing process and later it writes on console(jTextArea) --> "file.txt started to be hashing! It can take few minutes, please wait..", "file.txt is successfully hashed!!"
I'm working on a large text file and it takes a while to hash it. That's why i want to tell user he/she should wait a bit.
Why the working queue differs from my code order ?
Note: The only thing that came to my mind is to use thread, could it solve the problem?
Note: The only thing that came to my mind is to use thread, could it solve the problem?
Yes, that is correct. Code executed in an event listener is invoked on the Event Dispatch Thread. The GUI can't be repainted until all the code is finished executing. So a long running task prevents the GUI from repainting itself.
Read the section from the Swing tutorial on Concurrency in Swing for more information. Maybe a SwingWorker will be a better solution than creating your own Thread.
Use SwingWorker to implement a worker thread.
Do all the processing in doInBackground method, you can add your following code in doInBackground. Before that you can you will set the text in your console area. And once your file is hashed, you can implement done() method and set the appropriate message in your console area. To give you an idea, it will look something like this
#Override
protected Integer doInBackground() throws Exception {
try {
BufferedReader reader = new BufferedReader(new FileReader(myFile));
myHash = new HashOA(300000);
try {
while(reader.readLine() != null){
myHash.hash(reader.readLine());
}
return null;
} catch (IOException ex) {
Logger.getLogger(MainScreen.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(MainScreen.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
protected void done() {
consoleArea.append("\n" + myFile.getName() + " is successfully hashed!!");
}
Refer this for more clarity : How do I make my SwingWorker example work properly?
I'd like to know if there's a way where the Java SE allows a passage to be printed out and then in between the line we can allow the user to type the answer on the line.
To be more clear :
Here's an example:
____ reading, Alice also enjoys listening to classical music.
So, when the text is being drawn out using the buffer reader, the user is able to enter the answer on the line itself.
Here's the method of buffer reader:
public void getCloze(){
File file = new File("cloze.txt");
StringBuffer contents = new StringBuffer();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String text = null;
// repeat until all lines is read
while ((text = reader.readLine()) != null) {
contents.append(text)
.append(System.getProperty(
"line.separator"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// show file contents here
System.out.println(contents.toString());
}}
Hope someone can advise me how to and best if there's any tutorial to show the steps.
I dont think it is possible to prompt the user to type in between the already printed line in Java. you have to stop your priniting to take user input and then print further string to the user
It is not entirely clear what your problem is, but you seem to want to know how to write a question or prompt and allow the user to enter the answer on the same line. If so, the "trick" is to use System.out.print(prompt) rather than System.out.println(prompt); i.e. DON'T output a line break after the prompt.
UPDATE - I see what you are asking now.
Well the bad news is that there is no simple way to do that. However, it is doable using something like the charva library or a "curses for Java" library - What's a good Java, curses-like, library for terminal applications?
I have a program that takes in a file as an input and produces an xml file as an output. When I call this from the command line it works perfectly. I try calling it from a Java program with the following code.
try
{
Process proc = Runtime.getRuntime().exec(c);
try
{
proc.waitFor();
}
catch(InterruptedException e)
{
System.out.println("Command failed");
}
}
catch(IOException e)
{
System.out.println("Command failed");
e.printStackTrace();
}
The program seems to be running fine, as it creates an xml file; however, the xml file is empty when I open it. I'm not encountering any exceptions in my Java program, so I'm baffled as to what the problem could be. Why would the command line program work fine normally, but then when called from Java not output anything to the file it created. I was thinking maybe it was some sort of permissions thing. I tried running the program as sudo (I'm using Linux) but to no avail. This problem doesn't seem to be anything I could find an answer to online. Hopefully somebody on here might be able to tell what's going on. :)
Get the output and error streams from your process and read them to see what is happening. That should tell you what's wrong with your command.
For example:
try {
final Process proc = Runtime.getRuntime().exec("dir");
try {
proc.waitFor();
} catch (final InterruptedException e) {
e.printStackTrace();
}
final BufferedReader outputReader = new BufferedReader(new InputStreamReader(proc
.getInputStream()));
final BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc
.getErrorStream()));
String line;
while ((line = outputReader.readLine()) != null) {
System.out.println(line);
}
while ((line = errorReader.readLine()) != null) {
System.err.println(line);
}
} catch (final IOException e) {
e.printStackTrace();
}
If there is no output in either stream, then I would next examine the external program and the command being sent to execute it.
Did you try launching the process from outside java?
For me, I wrote a jar file that output a file and ran that from the command line in another java program. It turns out that there was a fundamental check in my jar file that I had forgotten about on the number of characters in an input string (my bad). If the count of the characters was smaller than 8 there was no output file. If the number of characters was greater than 8, the output file came out without any trouble using the following code:
String cmdStr = "java -jar somejar.jar /home/username/outputdir 000000001";
try
{
Runtime.getRuntime().exec(cmdStr);
Runtime.getRuntime().runFinalization();
Runtime.getRuntime().freeMemory();
log.info("Done");
}
catch (IOException e)
{
log.error(System.err);
}
Not sure if I really need everything here but, hey, it works. Note: no waitFor seems to be necessary in my case.
process input (actually output of the process!) and error streams has to be handled before waiting for the process termination.
This should work better
try
{
Process proc = Runtime.getRuntime().exec("anycomand");
BufferedReader outSt = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader errSt = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String line;
while ((line = outSt.readLine()) != null)
{
System.out.println(line);
}
while ((line = errSt.readLine()) != null)
{
System.err.println(line);
}
proc.waitFor();
}
catch (final IOException e)
{
e.printStackTrace();
}
but to understand better how Runtime exec works it is worth reading
the classic article
When Runtime.exec() won't
which provide useful sample code (better than the one above!)
How might I get the output from a CMD process to display in my GUI? This is the code I'm using to run the process:
try {
String line;
Process p = Runtime.getRuntime().exec("cmd /c \"e:\\folder\\someCommands.cmd\"");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
I've tried doing this:
jLabel1.setText(line);
...but the GUI is completely locked up while the process is running, so nothing updates until the very end, which isn't very useful. Other than that the CMD works fine. I just want to display the output in real-time.
Did you repaint() after setting the text of the label?
Anyway, you should generally be hesitant to execute a long operation on the GUI event thread. Look into using a SwingWorker instead.
You'll need to start a separate thread to run the process. The code you're using to run it can mostly just be inserted into the thread's (or Runnable's) run() method as is, but to set the text in the JLabel, you should use something like this:
...
while ((line = input.readLine()) != null) {
SwingUtilities.invokeLater(new SetTextRunnable(jLabel1, line));
}
...
class SetTextRunnable implements Runnable {
private String line;
private JLabel jLabel1
public SetTextRunnable(JLabel jLabel1, String line) {
this.jLabel1 = jLabel1;
this.line = line;
}
public void run() {
jLabel1.setText(line);
}
}
EDIT: just noticed something: apparently the class SwingWorker was designed for this sort of thing, so that's another option for you (if it exists in your version of Java).
EDIT to the EDIT: so silly me, I didn't notice SwingWorker was already mentioned in another answer.
In addition to what others have said about multithreading this - you'll also want to read the child process error stream. I believe that (in some instances) if you don't drain the error stream for the process it could cause it to hang.