Java查询大文本文件的处理方法

有时我们需要查询大文本而不是数据库,这时就需要流式读入文件并实现查询算法,还要进行并行处理以提高性能。但JAVA本身缺少相应的类库,需要硬编码才能实现结构化文件计算,代码复杂且可读性差,难以实现高效的并行处理。

使用免费的集算器可以弥补这一不足。集算器封装了丰富的结构化文件读写和游标计算函数,书写简单代码就能实现并行计算,并提供了易用的JDBC接口。JAVA应用程序可以将集算器脚本文件当做数据库存储过程执行,传入参数并用JDBC获得返回结果。

集算器与Java应用程序的集成结构如下:

下面举例说明集算器协助JAVA查询大文本的基本过程。源数据sOrder.txt如下:

要查询起止时间是startDate、endDate之间,金额大于argAmount的订单,只需使用如下代码:

A1:以游标方式打开文件。@t表示将第1行读为列名。

A2:进行结构化查询,结果为游标。

A3:执行游标,将结果读入内存,如下:

JAVA主程序可以JDBC的方式调用集算器脚本,代码如下:

Class.forName("com.esproc.jdbc.InternalDriver");

con=DriverManager.getConnection("jdbc:esproc:local://");

//调用集算器脚本(类似存储过程),其中searchbig是dfx的文件名

st=(com. esproc.jdbc.InternalCStatement)con.prepareCall("call searchbig");

//设置参数

st.setObject(1,"2010-01-01");

st.setObject(2,"2010-12-31");

st.setObject(3,2000);

//执行脚本

st.execute;

//获取结果集

ResultSetrs = st.getResultSet;

……

返回值是符合JDBC标准的ResultSet对象,调用集算器脚本和访问数据库的方法完全一样,熟悉JDBC的程序员可以很快掌握。

对于上面这类较简单的代码,还可以直接将脚本写在JDBC调用中,多行语句之间用\n分隔即可,类似执行一句较复杂的SQL,这样可以不必再保存一个脚本文件。

st = (com.esproc.jdbc.InternalCStatement)con.createStatement;

ResultSet rs1
=st.executeQuery("=file(\"D:\\sOrder.txt\").import@t\n"
+"=A1.select(OrderDate>=date(\"2010-01-01\")
&&OrderDate<=date(\"2010-12-31\") &&
Amount>2000)\n"+

"=A2.fetch");

集算器会返回最后一个表达式的值。

如果查询结果内存装不下,可以在集算器中直接返回游标(即去掉A3代码),在JAVA中只需设置每批次读取的记录数即可正常读取,具体代码如下:

st.setFetchSize(1000)

关于集算器JDBC的部署和调用的更详细信息可参考集算器集成应用之被JAVA调用

集算器还可以实现多线程并行计算,最简单方法就是在上述代码的cursor函数中使用@m,这表示多线程读取文件。

也可以手工分段,在读取和计算部分都使用多线程并行计算,代码如下:

A1:用8个游标打开文件,每次读取文件的指定部分。~表示循环变量,依次是1、2…8,@z表示将文件按字节数大致分为几部分,只读取其中一部分,集算器会自动去头补尾,以保证取出的数据是整行。

A2:针对每个游标执行查询。

A3:并行执行游标,并合并结果。@x表示合并的对象是游标,@m表示并行计算。需要注意的是,函数conj无法保证结果顺序和源数据一致。

上述代码使用了集算器内置的并行计算函数,如果计算过程较复杂,或内存可以装下计算结果,则适合用显式并行计算语句。代码如下:

A1:设定并行数。

A2:并行执行代码,作用范围是缩进的B2-B3。to(A1)=[1,2…8]表示每个线程的入口参数。线程内部可用A2来获取入口参数,线程外部可用A2获取所有线程的计算结果。

B3:查询游标,将结果读入内存,并返回给主线程。

A4:按顺序合并各线程的计算结果。

对于有序数据,可以用二分法来提高查询性能。比如数据已按Client和OrderID排序,现在要根据参数argClient和argOrder找出相应的记录,可以使用下面的代码:

begin,end是二分法的起止位置,m是中间位置。

B4:按字节数定位到中间位置,打开游标读入一条记录,集算器会自动实现去头补尾,取出完整记录。@x表示取出记录后立即关闭游标。

B5-C6:如果定位成功,则将当前记录存储在C5。

B7-C8:如果定位不成功,则继续比较集合大小并重新设置begin,end。

A9:将C5中的计算结果显式地返回给JDBC。

来源:51CTO

时间: 2024-10-27 13:45:56

Java查询大文本文件的处理方法的相关文章

.net读取大文本文件高效的方法

问题描述 .net读取大文本文件高效的方法 求教,使用.net读取大文本文件(200M~1G+)并将文本内容存放至数据库的制定table内,我尝试了几种方式要么速度太慢要么报内存溢出,求教高效方法.

java读写大文本文件的问题

问题描述 1.用Java读一个10以上的文本文件,需很多次读取其中一小部分内容,且每次读入的内容处理后才知道下次需读入的部分?求思路2.输出到一个新的文本文件,需输出的内容很多,必须分多次输出.当每次缓存到多大时输出,能获得最大效率? 解决方案 解决方案二:才有人问过这问题,参考下http://topic.csdn.net/u/20100713/09/5dfd2fa1-fefe-4f2a-854b-5077b669ccd2.html解决方案三:1题:使用BufferedInputStream效率

Linux 中如何打开一个大文本文件

在"大数据"时代,我们会经常遇到有大文本文件(上 GB 或更大)的情况.假设需要我们手工的搜索和编辑这些大文件,或者为了解决一些特定的问题而需要手工分析多个上 GB 的日志文件.传统的文本编辑软件对处理这样的大文件不太有效,当我们试图打开一个大文件时会经常由于内存不足而郁闷的不行. 如果你是一个精明的系统管理员,你也许会用 cat.tail.grep.sed.awk 等这些命令的组合来打开和编辑一个文本文件.在这篇教程里,我将会谈论关于如何在 Linux 中打开(并编辑)一个大文本文件

求大神指点 java无参带返回值方法问题

问题描述 求大神指点 java无参带返回值方法问题 max=(age>max)?age:max; 这这话是什么意思? 解决方案 max=(age>max)?age:max; 这是三步运算给max赋值,就相当于: f(age>max){ max=age; }else{ max=max; } 解决方案二: 如果age>max为真,则max=age,否则max=max 解决方案三: 如果age>max,就把age放入max 这个程序配合循环可以找到年纪最大的人 解决方案四: jav

java中List对象排序通用方法_java

本文实例讲述了java中List对象排序通用方法.分享给大家供大家参考.具体分析如下: 在数据库中查出来的列表list中,往往需要对不同的字段重新排序,一般的做法都是使用排序的字段,重新到数据库中查询.如果不到数据库查询,直接在第一次查出来的list中排序,无疑会提高系统的性能. 只要把第一次查出来的结果存放在session中,就可以对list重新排序了.一般对list排序可以使用Collections.sort(list),但如果list中包含是一个对象的话,这种方法还是行不通的.那要怎么排序

SQL Server参数化查询大数据下的实践

身为一名小小的程序员,在日常开发中不可以避免的要和where in和like打交道,在大多数情况下我们传的参数不多简单做下单引号.敏感字符转义之后就直接拼进了SQL,执行查询,搞定.若有一天你不可避免的需要提高SQL的查询性能,需要一次性where in 几百.上千.甚至上万条数据时,参数化查询将是必然进行的选择.然而如何实现where in和like的参数化查询,是个让不少人头疼的问题. where in 的参数化查询实现 首先说一下我们常用的办法,直接拼SQL实现,一般情况下都能满足需要.

MySQL中优化sql语句查询常用的30种方法

本篇文章是对MySQL中优化sql语句查询常用的30种方法进行了详细的分析介绍,需要的朋友参考下   1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以

java读取大文件简单实例

 这篇文章主要介绍了java读取大文件简单实例,有需要的朋友可以参考一下 我要从一个文本文件中提有用的数据  文本文件200多MB  是不是可以建一个缓存来把有用的数据一段一段的提出来,请问该怎么做?    JAVA中可以使用内存映射文件来操作大文件.  最大可达2GB.  下面是个简单的示例,更具体的自己看Java API DOCS或相关资料      代码如下: import java.io.*;  import java.nio.*;  import java.nio.channels.*

Java调用一个不存在的方法

问题描述 Java调用一个不存在的方法 请各位大神帮我解释一个问题,先看代码,谢谢! abstract class Base{ abstract public void myfunc(); public void another(){ System.out.println(""Another method""); } } public class Abs extends Base{ public static void main(String[] args){ Ab