按组处理大文件(结构化文本)
有这样一类文本文件:文件太大无法全部读入内存计算;但数据已按某列排序,如果以该列为标准每次读取一组数据,则可以放入内存进行计算。电信通话记录、网站访问记录、商场会员信息等等都属于此类文件。
JAVA实现此算法需要编写大量代码,过程复杂难以维护。使用集算器来辅助Java编程,这类问题就轻松许多。下面我们通过例子来看一下具体作法。
文本文件sOrder.txt存储着大量的订单信息,以tab为分隔符,第一行是列名,数据已按SellerId排序。现在需要每次读入SellerId相同的一组数据,并对每组数据执行同样的数据处理过程。
文件sOrder.txt的部分数据如下:
集算器脚本如下:
A1:函数cursor以游标方式打开文件,默认的分割符是tab,函数选项@t表示将第一行读为列名。如果只读取前四列,且分割符是逗号,则应当写作:cursor@t(OrderID, Client, SellerId, Amount; ”,”)
A2:for A1 ;SellerId。对游标A1进行循环读数,每次读入SellerId相同的一组数据,此时数据才会真正读入内存。
注意这里的for 语句。集算器有for cs,n这样的写法,这表示每次读入游标cs中的n条记录。而for cs;x表示每次读入游标cs中的一组记录,每组记录的x字段相同,数据需要按照x事先排序。本案例的数据已经排过序了,如果尚未排序,则可先用sortx函数排序。
语句for cs;x中的x不止是字段,也可以是表达式,即:每次读入多条数据,直到表达式x发生变化,比如:for A14 ;floor(SellerId/10)。这句代码会将SellerId从0到9的数据归为一组,10到19的归为下一组,函数floor表示取整数部分。如果每个SellerId对应的记录比较少,则上述语句可以一次性读入更多的数据,从而提高计算性能。
B3-C3:这是for语句的循环体,用来对每组数据进行同样的数据处理。处理过程并非本文重点,本案例设计为:计算每个销售员(SellerId)的销售额,如果销售额大于10000,则将该销售员的销售记录追加到文件result.txt。
值得注意的是,for语句的作用范围用缩进就可以表示,而无需用括号或begin/end等标记。另外,循环变量用for所在单元格的格名就可以表示,即A2表示当前SellerId对应的记录,A2.sum(Amount)表示对这组记录的Amount字段使用求和函数。函数export用来将一组记录输出到文件中,函数选项@a表示以追加的方式输出。
文件result.txt存储着计算结果,部分数据如下:
上述脚本已经完成了所有的数据处理工作,接下来通过JDBC将集算器脚本集成在JAVA里,具体的JAVA代码如下:
//建立esProc jdbc连接
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
//调用esProc,其中test是脚本文件名
st =(com.esproc.jdbc.InternalCStatement)con.prepareCall("call test()");
st.execute();//执行esProc存储过程
说明:本案例不要求将计算结果返回JAVA,但有时我们会将计算结果追加在单元格中(假设是B2格),并将结果返回JAVA继续加工。这种情况下需要在集算器中增加一句脚本,比如在A4格书写:result B2,这表示将B2里的数据输出到JDBC接口。
接下来的JAVA代码也需要增加一句代码,用来接收返回的结果,即在execute之后书写:
ResultSet set = st.getResultSet(); 。
推荐阅读
-
Python文本处理之按行处理大文件的方法
-
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)
-
Python文本处理之按行处理大文件的方法
-
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)
-
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)
-
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)
-
按组处理大文件(结构化文本)
-
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)_php实例
-
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)_php实例
-
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)_PHP教程