Member Avatar for v3ga

My objective is to implement a GUI calculator in java. I am thinking of passing the expression entered by the user to bc and then get output from terminal and print to user. My question is

  1. How to execute a terminal command from java so that i can pass the expression to bc
  2. How to get output from terminal. Right now I am thinking of redirecting terminal to file and then reading from file but please tell me if it is possible to do directly.

My objective is to implement a GUI calculator in java. I am thinking of passing the expression entered by the user to bc and then get output from terminal and print to user. My question is

  1. How to execute a terminal command from java so that i can pass the expression to bc
  2. How to get output from terminal. Right now I am thinking of redirecting terminal to file and then reading from file but please tell me if it is possible to do directly.

Console Output

//diplays text to console
System.out.print("Hello "); 
System.out.println("world");

Console Input

//gets input from console
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
String text = in.readLine();

check this too:http://www.javapractices.com/topic/TopicAction.do?Id=79 and this:http://www.homeandlearn.co.uk/java/user_input.html

Google the ProcessBuilder class ...

commented: ty +3
Member Avatar for v3ga

Maybe my question was not clear. I want to use the bc calculator in unix terminal. Similar to system() function in C. For example, if I want to find 2^1000, I can enter in the UNIX terminal
echo 2^1000 | bc
and the output appears on the terminal. I am implementing a GUI calculator something similar to a fromt end for bc so I want to send the command
echo expr | bc
to the terminal where expr is the expr I want to evaluate& get the output from the terminal for use in the program.

Maybe my question was not clear. I want to use the bc calculator in unix terminal. Similar to system() function in C. For example, if I want to find 2^1000, I can enter in the UNIX terminal
echo 2^1000 | bc
and the output appears on the terminal. I am implementing a GUI calculator something similar to a fromt end for bc so I want to send the command
echo expr | bc
to the terminal where expr is the expr I want to evaluate& get the output from the terminal for use in the program.

did you check up on what jamescherrill recommended... because the ProcessBuilder class will allow you to call bc, and send input to and get input from streams it, thus being exactly what you want... check here:http://stackoverflow.com/questions/525212/how-to-run-unix-shell-script-from-java-code and here:http://stackoverflow.com/questions/2144165/execute-with-parameters and java docs:http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html and this:http://www.javabeat.net/tips/8-using-the-new-process-builder-class.html

Member Avatar for v3ga

Jamescherill made the post while I was posting.
Thanks for the reply. So I need to make a processbuilder and start the process bc.
I have one other doubt. I started a process bc. Now should I write my expression into the stream returned by getInputStream or that returned by getOutputStream
(Sorry If I sound noobish but the javadocs for Process class says this about the function getOutputStream--"Gets the output stream of the subprocess. Output to the stream is piped into the standard input stream of the process represented by this Process object." Thats why I am a bit confused)

Yes, that can be confusing! In your java code you write data to the Output stream, and you read the results back from the Input stream. Ie "input" and "output" are as seen from the Java end of the pipes.

Member Avatar for v3ga

Also for reading and writing from/to streams which method should I use? Can I use Scanner & Printwriter?

Yes

Sorry for previous terse reply - I just had a few seconds and thought it better brief than do nothing.
Anyway, more time now...
You can use any character-oriented streams - the ones you're familiar with would be an obvious choice. Here's a really good link about some problems that you 'll probably run into... and their solutions)
http://stackoverflow.com/questions/3643939/java-process-with-input-output-stream

Member Avatar for v3ga

This is my class

public class BcCalc
{
    private ProcessBuilder pb;
    private Process CalcProcess;
    private BufferedReader reader; 
    private BufferedWriter writer; 
    public BcCalc()
    {
        try
        {
            pb=new ProcessBuilder("bc","-l");
            pb.redirectErrorStream(true);
            CalcProcess=pb.start();
            reader = new BufferedReader (new InputStreamReader(CalcProcess.getInputStream()));
            writer = new BufferedWriter(new OutputStreamWriter(CalcProcess.getOutputStream()));
            
        } catch (IOException ex)
        {
            Logger.getLogger(BcCalc.class.getName()).log(Level.SEVERE, null, ex);
        }        
    }
    public void writeToTerminal(String str)
    {
        try
        {
            writer.write(str);
        } catch (IOException ex)
        {
            Logger.getLogger(BcCalc.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public String readFromTerminal()
    {
        try
        {
            return reader.readLine();
        } catch (IOException ex)
        {
            Logger.getLogger(BcCalc.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";
    }
    public void StopProcess()
    {
        CalcProcess.destroy();
    }
}

The actionPerformed method of equals button is

private void ButEqualsActionPerformed(java.awt.event.ActionEvent evt)                                          
    {                                              
        myCalc.writeToTerminal(ExprField.getText());
        ExprField.setText(myCalc.readFromTerminal());
    }

Here mycalc is an object of BcCalc class.
My code is not working. The whole program hangs when I press the equals button and there is nothing on the logger either. What am I doing wrong?
(ExprField is a JTextField used for display of the calculator

1. Put a load of print statements into your code, printing the values of the key variables at each stage so you cen see where it's going wrong.
2. Do you need a \n at the end of your writeToTerminal string?

Member Avatar for v3ga

Thanks It worked. Had forgotten about \n. Just added \n and flushed the writer. :)
Also I wrote the code for actionPerformed events of various buttons like Exprfield.settext(Exprfield.gettext+"4");//for the button 4
Is there a better way that will insert 4 at the current caret position rether than at the end of the string as I have done

Depends on exactly what you are trying to do, but in general
Exprfield.getDocument() will give you the Document object that handles the input and editing of what you see in the text field. Once you have the Document you can insert text at the caret or do whatever else you want

Member Avatar for v3ga

Thanks a lot. I managed to get it to work. What I wanted to do was that a button should insert the text at the caret position and not at the end of the expression.
But I ran into another problem.
I changed the code of reading from the output of bc to this.

public String readFromTerminal()
    {
        String readString="";
        try
        {
            if(stdin.ready())
            {
                while(stdin.ready())
                    readString=readString+Character.toString((char)stdin.read());
            }
        } catch (IOException ex)
        {
            Logger.getLogger(BcCalc.class.getName()).log(Level.SEVERE, null, ex);
        }
        return readString;
    }

I had to do it because scanner is not reading the full output if the numbers are large(eg.100!). But now there is a weird error. I have to press the equals button twice to get the answer printed in the textfield. I didn't change its event handling code.

private void ButEqualsActionPerformed(java.awt.event.ActionEvent evt)
{
myCalc.writeToTerminal(ExprField.getText());
ExprField.setText(myCalc.readFromTerminal());

Please tell me where am I going wrong?

Member Avatar for v3ga

Bump

Why not go back top readLine like your earlier attempt and parse the input Stirng yourself. No harder than a Scanner, but much more under your control.

Member Avatar for v3ga

Thanks a lot for your help

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.