如何通过在 java 中使用 Runtime.exec() 运行 sqlplus 来捕获 sqlplus 窗口的输出

Posted

技术标签:

【中文标题】如何通过在 java 中使用 Runtime.exec() 运行 sqlplus 来捕获 sqlplus 窗口的输出【英文标题】:How to capture output from sqlplus window by running sqlplus using Runtime.exec() in java 【发布时间】:2017-04-27 06:52:02 【问题描述】:

我正在尝试从 java 运行 sql 脚本(此处为 memo_222dataFERG.out)并尝试从 sqlplus 窗口捕获输出。这是我的代码

Runtime rt = Runtime.getRuntime();
                                String runString1 = "cmd /c start sqlplus pecok/pecok@xe @C:\workspace\PeCok_Tool\memo_222dataFERG.out";  
                                Process proc = null; 
                                proc = rt.exec(runString1);
                            //  proc = rt.exec("java -version");
                                InputStream is = proc.getErrorStream();
                                //InputStream is = proc.getInputStream();
                                int bufSize = 4096; 
                                BufferedReader in = new BufferedReader(new InputStreamReader(is), bufSize);
                                String currentLine = null; 
                                while ((currentLine = in.readLine()) != null) 
                                    System.out.println(" "  + currentLine); 
                                
                                is.close();
                                int a = proc.waitFor();
                                System.out.println(" proc.waitFor() :: " +a);

Sqlplus 执行。 SQLPlus 窗口打开并开始执行我在 C:\workspace\PeCok_Tool\memo_222dataFERG.out 文件中编写的插入语句。但我无法从 sqlplus 窗口捕获输出并在 Eclipse 控制台中打印。在 while 循环中的某个地方它挂起并且没有在 Eclipse 控制台中打印任何内容。但是当我运行 "java -version"(在代码中注释)时,它成功地将 java 版本打印为控制台中的输出。现在我的问题是如何读取 sqlplus 窗口的输出?我尝试了 getErrorStream() 和 getInputStream()。

【问题讨论】:

如果直接从命令提示符运行命令会发生什么?您的脚本是否以“exit”结尾? 不...脚本中没有退出。 好吧,这是你的问题;如果您不退出,则 SQL*Plus 会坐在那里等待更多输入。 See this. 谢谢亚历克斯。我把退出放在脚本中。现在它工作正常。 Problem running oracle script from command line using sqlplus的可能重复 【参考方案1】:

我知道您特别询问 sqlplus 和进程分叉,但是 SQLcl 运行 sqlplus 所做的任何事情,并且完全用 java 编写,因此易于集成。

我在这里有一个 github 存储库,专门针对如何执行此操作:https://github.com/oracle/oracle-db-tools/tree/master/sqlcl/java

这是其中一个 java 示例:

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import oracle.dbtools.raptor.newscriptrunner.ScriptExecutor;
import oracle.dbtools.raptor.newscriptrunner.ScriptRunnerContext;

public class RunMyScript 

  public static void main(String[] args) throws SQLException, UnsupportedEncodingException 
    Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//localhost:1521/XE", "klrice", "klrice");
    conn.setAutoCommit(false);

    // #create sqlcl
    ScriptExecutor sqlcl = new ScriptExecutor(conn);

    // #setup the context
    ScriptRunnerContext ctx = new ScriptRunnerContext();

    // #set the context
    sqlcl.setScriptRunnerContext(ctx);
    ctx.setBaseConnection(conn);

    // Capture the results without this it goes to STDOUT
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    BufferedOutputStream buf = new BufferedOutputStream(bout);
    sqlcl.setOut(buf);


    // # run a whole file 
    // adjust the path as it needs to be absolute
    sqlcl.setStmt("@/Users/klrice/workspace_commons/sqlcl-java/myfile.sql");
    sqlcl.run();


    String results = bout.toString("UTF8");
    results = results.replaceAll(" force_print\n", "");
    System.out.println(results);
  


【讨论】:

以上是关于如何通过在 java 中使用 Runtime.exec() 运行 sqlplus 来捕获 sqlplus 窗口的输出的主要内容,如果未能解决你的问题,请参考以下文章