Question

I use the following two methods to run sqlite3.exe manually.

  1. If I type 'sqlite3.exe test.db' at the Windows command line, sqlite3 enters its interactive shell where I can enter various commands.

  2. If instead I enter a third SQL argument, eg. 'SQLite.exe test.db "SELECT * FROM clients"', sqlite3 does not run interactively, but the requested data is output through stdout.

I would like interact with the prompts in the shell from java code (the first scenario).

Using the following quick Java code I can run SQLite3.exe non-interactively (the second scenario).

    char[] readBuffer=new char[1000];

    //Third parameter in constructor is the select statement
    ProcessBuilder pBuilder=new ProcessBuilder(pathToSQLite3exe, "test.db",
     "\"SELECT * FROM clients"\" ); 

    pBuilder.directory(new File(pathToExeFolder));
    pBuilder.redirectErrorStream(true);

    Process process=pBuilder.start();

    InputStreamReader reader=new InputStreamReader(process.getInputStream());

    int charCount;

    while (true)
    {
        charCount=reader.read(readBuffer);
        if (charCount>0)
        {
            System.out.print(new String(readBuffer,0,charCount));
        }
        else
        {
            break;
        }
    }

The above works as expected, but if I omit the third parameter (the select statement) in the ProcessBuilder constructor, the program pauses eternally, presumably at the reader.read() statement because there are no characters to read. I suppose sqlite3.exe has indeed entered interactive mode, but the input stream is not fed by the stdout of the shell. I was hoping to see the interactive prompt text and be able to write commands to the output stream.

Is this possible with Java and ProcessBuilder?

Thanks.

Was it helpful?

Solution

From the Process javadoc: http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html

By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), and getErrorStream(). The parent process uses these streams to feed input to and get output from the subprocess.

You can get the OutputStream from the Process and write to it what you would normally type directly in to the console when running SqlLite interactively.

OutputStream os = process.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("SELECT * FROM clients;");
bw.newLine();
bw.flush();

Then read the InputStream like you do already, it should have the output you would normally see when running SqlLite interactively.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top