如何通过在 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 窗口的输出的主要内容,如果未能解决你的问题,请参考以下文章

如何通过在eclipse中使用指定的java路径目录而不是默认的Java路径来运行eclipse

如何在 Java 中使用 PSK 通过 MQTT 建立安全通信?

如何通过 onItemClickListener 在不同的类( ConsumerDescAndEdit.java )中使用某个类的变量?

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

如何通过 Java 在 SQLite 中强制执行外键约束?

java - 如何使用正则表达式作为过程中的参数通过java执行sql过程?