首页 > 其他 > 详细

条件查询大文本文件的通用办法

时间:2015-01-21 02:12:13      阅读:364      评论:0      收藏:0      [点我收藏+]

在进行文本处理时,经常会遇到对大文件进行条件查询的情况。用命令行的grep\cat可以处理一些简单情况,写法很简单,但效率太低,用高级语言处理此类问题虽然可以获得较高的运行效率,但代码编写复杂度却相当高。如果遇到条件比较复杂或条件经常变化的情况,还需要额外实现一套类SQL的底层库函数,其难度会更大。

集算器支持大文件条件查询和多线程并行计算,代码简洁性能优异,下面通过例子来看一下具体作法。

文本文件employee.txt中保存了员工数据。现在要读取员工信息,从中找出198111日(含)之后出生的女员工,最后将查询结果输出到result.txt中。

???????? 文本文件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

?

集算器代码:


bubuko.com,布布扣


? ??
A1:以游标的形式打开文件。函数cursor并不会将数据全部读入内存,而是以游标(流)的方式打开文件,因此不会占据内存空间。函数cursor使用了默认参数,即:以tab为列分割符读入全部的字段。选项@t表示文件的第一行是列名,之后可以使用直观的列名来书写表达式,如果没有这个选项,则会自动命名为_1_2_3…_n

A2=A1.select(${where})

按照条件过滤。这里使用宏来实现动态解析表达式,其中的where就是动态传入的参数,需要提前定义。定义参数的界面如下:


bubuko.com,布布扣
?

集算器会先计算${…}里的表达式,将计算结果作为宏字符串值替换${…}之后解释执行。比如按照案例中的条件给where赋值为BIRTHDAY>=date(1981,1,1) && GENDER=="F",则A2的表达式会被替换为=A1.select(BIRTHDAY>=date(1981,1,1) && GENDER=="F")。参数可以在IDE中输入,也可以来自JAVA代码和命令行。

A3=file("D:/result.txt").export@t(A2)将计算结果输出到文件中。如果计算结果总是很小,也可以用=A2.fetch()将计算结果放入内存并直接观察,或者用result A2.fetch()将计算结果返回给JAVA程序。

本案例的最终结果如下:


bubuko.com,布布扣


?
???????? 本案例实现的是动态查询,即过滤条件发生变化时不用改变代码,只需改变where参数即可。例如,条件变为:查询198111日(含)之后出生的女员工,或者NAME+SURNAME等于”RebeccaMoore”的员工。Where的参数值可以写为:BIRTHDAY>=date(1981,1,1) && GENDER=="F" || NAME+SURNAME=="RebeccaMoore"。执行之后,A2中的结果集如下图:


bubuko.com,布布扣


?
前面的算法是串行,改成并行可以进一步提高性能,具体做法是用多个线程并行读取文件,每个线程都用游标访问文件的一部分,并同时进行条件查询,最后再将每个游标的结果合并。

集算器并行计算的代码如下:


bubuko.com,布布扣


? ? ?
A1=4A1是分段数量,即将文件分成4段。分段数量,也就是实际执行时的并行数,一般不要超过CPU的核数,否则会形成排队等待,并不能提高性能。实际使用最大并行数量可以在选项中配置。

A2=A1.(file("d:/employee.txt").cursor@z(;, ~:A1))

上面的代码按照分段数量生成4个游标。其中A1.(express)表示按照括号内的表达式依次计算A1的成员,括号内可用“~”来表示当前成员。A1一般是集合,比如["file1", " file2"][2,3]A1如果是从1开始的连续数字,比如[1,2,3,4],则可以简写成4.( express),案例中的代码就是这种情况。

括号内的表达式是file("d:/employee.txt ").cursor@z(;, ~:A1),其中函数cursor使用了选项@z,这表示将文件分段,用游标取其中的某一段。~:A1表示文件会被大致分为4(A1=4),当前取第~段。“~”是A1的当前成员,因此每个游标依次对应第1、第2、第3、第4段文件。

另外,之所以是“大致分”,是因为精确分会出现半行数据的情况,而集算器会去头补位,自动取出整行数据。

A3=A2.(~.select(${where}))这句代码针对A2中的每个游标(即~)进行计算,求查询出游标中符合条件的行数据。这里的计算结果仍然是四个游标。

A4=A3.conj@xm()这句代码将A3中的多个游标进行并行合并。

A5=file("d:/result.txt”).export(A4),将最终计算结果输出到文件中。? ? ??

?

条件查询大文本文件的通用办法

原文:http://datamachine.iteye.com/blog/2177643

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!