zoukankan      html  css  js  c++  java
  • 集算器协助Java处理结构化文本之分组汇总

    直接用Java实现文体文件分组汇总会有如下的麻烦:

    1、文件不是数据库,不能用SQL访问。当分组、汇总表达式变化时,只能改写代码。而要实现灵活表达式的话,需要自己实现动态表达式解析和求值,编程工作量非常大。

    2、遍历过程中记录分组结果,结果小了还可以存在内存中,如果分组结果太大时要将中间结果缓存进临时文件再归并,实现过程非常复杂。

    使用集算器辅助Java编程,这些问题都有现成的类库可以解决。下面,我们通过例子来看一下具体作法。

    文本文件employee.txt中保存有员工信息,我们要按照DEPT分组,求出每组的员工个数COUNT和薪酬SALARY总额。

    文本文件empolyee.txt的格式如下:

        EID NAME SURNAME GENDER STATE BIRTHDAY HIREDATE DEPT SALARY
        1 Rebecca Moore F California 1974-11-20 2005-03-11 R&D 7000
        2 Ashley Wilson F New York 1980-07-19 2008-03-16 Finance 11000
        3 Rachel Johnson F New Mexico 1970-12-17 2010-12-01 Sales 9000
        4 Emily Smith F Texas 1985-03-07 2006-08-15 HR 7000
        5 Ashley Smith F Texas 1975-05-13 2004-07-30 R&D 16000
        6 Matthew Johnson M California 1984-07-07 2005-07-07 Sales 11000
        7 Alexis Smith F Illinois 1972-08-16 2002-08-16 Sales 9000
        8 Megan Wilson F California 1979-04-19 1984-04-19 Marketing 11000
        9 Victoria Davis F Texas 1983-12-07 2009-12-07 HR 3000
        10 Ryan Johnson M Pennsylvania 1976-03-12 2006-03-12 R&D 13000
        11 Jacob Moore M Texas 1974-12-16 2004-12-16 Sales 12000
        12 Jessica Davis F New York 1980-09-11 2008-09-11 Sales 7000
        13 Daniel Davis M Florida 1982-05-14 2010-05-14 Finance 10000
        …

    实现的思路是:用Java程序调用集算器脚本,读取和计算数据,之后将结果以ResultSet的方式返回给Java程序。由于集算器支持动态表达式解析和求值,使得Java程序可以像使用sql那样,灵活的处理文本文件中的数据。

    例如,我们需要按照DEPT分组,求出每组的员工个数COUNT和薪酬SALARY总额,esProc程序可以从外部传入一个输入参数“groupBy”作为动态的分组和汇总条件,如下图:

    “groupBy”的值是:DEPT:dept;count(~):count,sum(SALARY):salary。esProc代码如下:

    A1:定义一个file游标对象,第一行是标题,字段分隔符默认是tab。esProc的集成开发环境可以直观的显示出导入的数据,如上图右边部分。

    A2:按照指定字段分组汇总。这里使用宏来实现动态解析表达式,其中的groupBy就是传入参数。集算器将先计算${…}里的表达式,将计算结果作为宏字符串值替换${…}之后解释执行。这个例子中最终执行的是:=A1.groups(DEPT:dept;count(~):count,sum(SALARY):salary)。

    A3:向外部程序返回符合条件的结果集。

    分组字段发生变化时不用改代码,只需改变groupBy参数即可。例如,分组变为:按照DEPT和GENDER两个字段分组,求出每组的员工个数COUNT和薪酬SALARY总额。groupBy的参数值可以写为:DEPT:dept,GENDER:gender;count(~):count,sum(SALARY):salary。

    针对所有数据的简单汇总计算可以看作是分组汇总的一种特殊情况。例如:要统计全部员工的个数和薪酬总数,这时可将groupBy参数值写为:;count(~):count,sum(SALARY):salary,即分组的部分填空,相当于把所有数据只分成一个组。这样做的好处是可以一次遍历计算出这批数据的多个汇总值。

    在Java程序中通过集算器的jdbc调用这段esProc程序(保存为test.dfx文件)的代码如下:

        //建立esProc jdbc连接
        Class.forName(“com.esproc.jdbc.InternalDriver”);
        con= DriverManager.getConnection(“jdbc:esproc:local://”);
        //调用esProc 程序(存储过程),其中test是dfx的文件名
        com.esproc.jdbc.InternalCStatement st;
        st =(com.esproc.jdbc.InternalCStatement)con.prepareCall(“call test(?)”);
        //设置参数
        st.setObject(1,”DEPT:dept,GENDER:gender;count(~):count,sum(SALARY):salary”);//参数就是动态的分组汇总字段
        //执行esProc存储过程
        st.execute();
        //获取结果集
        ResultSet set = st.getResultSet();

    对于代码较简单的脚本,还可以把代码直接写在调用集算器JDBC的Java程序中,而不必专门编写脚本文件(test.dfx):
        st=(com. esproc.jdbc.InternalCStatement)con.createStatement();
        ResultSet     set=st.executeQuery(“=file(”D:/employee.txt”).cursor@t().groups(DEPT:dept,
    GENDER:gender;count(~):count,sum(SALARY):salary)”);

    这段Java代码直接调用了集算器的一句脚本:从文本文件中取得数据处理后,结果集返回给ResultSet对象set。

    如果分组结果集还是比较大而不能在内存装入,则要使用groupx语句用文件游标的方式返回分组结果。集算器代码将调整如下:

    groups函数把分组汇总的结果完全放在内存中,而groupx则当分组汇总结果大于缓冲行数的时候会把结果写入临时文件,并重新利用内存。之后,groupx再将生成的临时文件归并。这里的参数1000000就是指缓冲行数,取值原则是充分利用内存,以尽量减少缓存文件的数量。这个数量和物理内存大小及记录本身的大小都有关,需要编程时估算,一般建议在几十万到上百万的量级。

    虽然A3单元格给Java返回的不是结果集而是游标,但是Java调用的程序不用修改。在Java使用ResultSet遍历数据的时候集算器会自动读取游标对应的内容。

    这段程序可以再完善以支持分组前和分组后过滤,类似SQL中的where和having。例如:统计对象变为只统计女员工(GENDER==”F”),并且分组汇总之后,只保留女员工个数大于10的部门。具体代码如下:

    为了方便理解,这里没有再使用网格参数,实际上写法和前述代码是一样的:A2.groupx(${groupBy})。select函数的参数也可以写成宏,从Java程序中传进来。

  • 相关阅读:
    start tag, end tag issues in IE7, particularly in xslt transformation
    用SandCastle为注释生成chm文档
    Firebug
    架构的重点
    Linux Shell常用技巧(十) 管道组合
    Linux JDK升级
    Linux Shell常用技巧(十二) Shell编程
    Packet Tracer 5.0实验(一) 交换机的基本配置与管理
    Linux Shell常用技巧(六) sort uniq tar split
    Linux Shell常用技巧(二) grep
  • 原文地址:https://www.cnblogs.com/raqsoft/p/5065683.html
Copyright © 2011-2022 走看看