大文本文件的分组汇总办法_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 大文本文件的分组汇总办法

大文本文件的分组汇总办法

 2015/3/17 15:52:43  datamachine  程序员俱乐部  我要评论(0)
  • 摘要:直接用Java实现文体文件分组汇总会有如下的麻烦:1、文件不是数据库,不能用SQL访问。当分组、汇总表达式变化时,只能改写代码。而要实现灵活表达式的话,需要自己实现动态表达式解析和求值,编程工作量非常大。2、遍历过程中记录分组结果,结果小了还可以存在内存中,如果分组结果太大时要将中间结果缓存进临时文件再归并,实现过程非常复杂。使用集算器辅助Java编程,这些问题都有现成的类库可以解决。下面,我们通过例子来看一下具体作法。文本文件employee.txt中保存有员工信息,我们要按照DEPT分组
  • 标签:文件

class="MsoNormal" style="text-indent: 21.0pt;">直接用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):salaryesProc代码如下:



?

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

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

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

分组字段发生变化时不用改代码,只需改变groupBy参数即可。例如,分组变为:按照DEPTGENDER两个字段分组,求出每组的员工个数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 程序(存储过程),其中testdfx文件名

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();

对于代码较简单的脚本,还可以把代码直接写在调用集算器JDBCJava程序中,而不必专门编写脚本文件(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中的wherehaving。例如:统计对象变为只统计女员工(GENDER=="F"),并且分组汇总之后,只保留女员工个数大于10的部门。具体代码如下:



?

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

  • 大小: 25.5 KB
  • 大小: 11.8 KB
  • 大小: 12.8 KB
  • 大小: 27 KB
  • 查看图片附件
发表评论
用户名: 匿名