如何有效地获得结果的最后一个值

时间:2016-06-14 13:08:05

标签: java java-ee hive

我正在尝试从java文件执行配置单元查询。我想只获取show database查询的最后一个结果。

有没有办法直接指向最后一个输出,而不是遍历所有查询结果以找出最后一个值。

example : show databases ;
Db1 
DB2
DB3

Output should be DB3 

public class Test {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {

        ProcessBuilder hiveProcessBuilder = new ProcessBuilder("hive", "-e",
                "show databases");
        Process hiveProcess = hiveProcessBuilder.start();

        OutputRedirector outRedirect = new OutputRedirector(
                hiveProcess.getInputStream(), "HIVE_OUTPUT");
        OutputRedirector outToConsole = new OutputRedirector(
                hiveProcess.getErrorStream(), "HIVE_LOG");

        outRedirect.start();
        outToConsole.start();
    }

    public static class OutputRedirector extends Thread {

        InputStream is;
        String type;

        public OutputRedirector(InputStream is, String type) {
            this.is = is;
            this.type = type;
        }

        @Override
        public void run() {
            try {
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String line = null;

                while ((line = br.readLine()) != null) {
                    String result = line;
                    System.out.println(type + "> " + result);
                }
            } catch (IOException ioE) {

            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

一般来说,您通常会在输入流中解析并等待所需的内容。

但是,当您尝试捕获命令行程序的输出时,您还不知道它何时完成。因此,我不会使用BufferedReader,而是使用InputStreamReader本身定期读取字符。你可以通过读取每秒钟的几个字符来做到这一点,并记住最后一个换行符以了解你的整行。

最后,您应该检查一个指示符,该指示符显示您已到达结果集的末尾。

此外,此线程将永远运行,因此如果您不再需要它,但您不想关闭父进程(例如应用程序本身),则必须使用中断来关闭正确处理,您可以在此处查看如何操作:http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

    @Override
    public void run() {
        try {
            InputStreamReader in = new InputStreamReader(is);
            StringBuilder buffer = new StringBuilder();
            String currentLastLine = null;

            while (true) {
                int nextchar = in.read();
                //nextchar == -1 -> we are at the end of the stream
                if (nextchar == -1) {
                    Thread.sleep(1000);
                } else {
                    buffer.append(nextchar);
                }

                //new line here
                if (nextchar == 10) {
                    // check for end of result indicator
                    String newLastLine = buffer.toString();
                    // this could be something like .contains('hive >') as well
                    // END_OF_RESULT_SET must be defined according to your output
                    if (newLastLine.matches(END_OF_RESULT_SET)) {
                        // here currentLastLine is your desired line,
                        // so do something with it
                        System.out.println("Result: "+currentLastLine);
                    }

                    currentLastLine = newLastLine;
                    buffer = new StringBuilder();
                }

            }
        } catch (IOException ioE) {
          ...
        } catch (...) {
          ...
        }
    }

答案 1 :(得分:0)

正如我所看到的,Process类只支持流,请参阅 https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html

流的概念是顺序访问,所以除非你的进程没有一些Java接口API(比如用于访问Oracle数据库的OJDBC),否则你只能遍历你的流,直到你到达最后一行,我对不起。