我使用以下两种方法手动运行sqlite3.exe。
如果我在Windows命令行输入'sqlite3.exe test.db',sqlite3会进入其交互式shell,我可以输入各种命令。
如果我输入第三个SQL参数,例如。 'SQLite.exe test.db“SELECT * FROM clients”',sqlite3不以交互方式运行,但请求的数据通过stdout输出。
我想从java代码(第一个场景)中与shell中的提示进行交互。
使用以下快速Java代码,我可以非交互式运行SQLite3.exe(第二种方案)。
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;
}
}
上面按预期工作,但是如果我在ProcessBuilder构造函数中省略第三个参数(select语句),则程序会永久停顿,大概是在reader.read()语句中,因为没有要读取的字符。我想sqlite3.exe确实进入了交互模式,但输入流不是由shell的stdout提供的。我希望看到交互式提示文本,并能够将命令写入输出流。
Java和ProcessBuilder有可能吗?
感谢。
答案 0 :(得分:2)
来自Process
javadoc:http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
默认情况下,创建的子进程没有自己的终端或控制台。它的所有标准I / O(即stdin,stdout,stderr)操作将被重定向到父进程,在那里可以通过使用方法getOutputStream(),getInputStream()和getErrorStream()获得的流来访问它们。父进程使用这些流向子进程提供输入并从子进程获取输出。
您可以从Process获取OutputStream,并在交互式运行SqlLite时将其直接写入控制台中,然后将其写入。
OutputStream os = process.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("SELECT * FROM clients;");
bw.newLine();
bw.flush();
然后像你一样读取InputStream,它应该具有你在交互运行SqlLite时通常会看到的输出。