你的位置:首页 > Java教程

[Java教程]用集算器协助Java读入文本


  JAVA提供了最基本的文件处理函数,可以简单无结构的方式读入小文本文件,如果遇到需要结构化、格式多样、要求特殊的文件或内存装不下的大文件,相应的代码就会很复杂,可读性和复用性也很难保障。

  使用免费的集算器可以弥补这一不足。集算器封装了丰富的结构化文件读写和计算函数,并提供JDBC接口。JAVA应用程序可以将集算器脚本文件当做数据库存储过程执行,传入参数并用JDBC获得返回结果。详情参考集算器用作Java计算类库的应用结构

  下面说明JAVA读入文本的常见案例,以及集算器对应的解法。

读入指定列
  按列名读入sOrder.txt中的3列:OrderID、Client、Amount。源数据如下:

esProc_java_retrieve_text_2

  集算器代码:

 A
1=file(“D: \\sOrder.txt”).import@t(OrderID,Client,Amount)

  结果:

esProc_java_retrieve_text_4

  1. @t表示将第1行读为列名。文件不含列名时可用序号引用各列,比如读入第1、2、4列,可用这句代码:file(“D: \\sOrder.txt”).import(#1,#2,#4),结果如下:

esProc_java_retrieve_text_5

  2. 如果要输出计算列,比如将年份和OrderID拼成newOrderID,并和Client、Amount一同输出,可用如下代码:

 A
1=file(“D: \\sOrder.txt”).import@t()
2=A1.new(string(year(OrderDate))+”_”+string(OrderID):newOrder,Client,Amount)

  函数import默认读入所有字段,new函数可创建新二维表,结果如下:

esProc_java_retrieve_text_7

  3. 默认分割符是tab,也可用其他字符,比如读入以逗号为分隔符的csv文件,可用这句代码file(“D: \\sOrder.txt”).import@t(;”,”)。

  4. 如果只输出部分行,可以按行号指定,比如输出2-100行,代码是A1.to(2,100),从第3行开始输出,代码是A1.to(3,)。

  5. 个别情况下会按列读入,比如将OrderID,Client,Amount纵向拼成1列输出,读入数据后可用下面的代码实现:create(all).record(A1.(OrderID)|A1.(Client)|A1.(Amount)) 。

读取大文件

  对于超过内存的大文件,可用集算器游标读取文件,JAVA用JDBC流访问。

  集算器代码:

 A
1=file(“D: \\sOrder.txt”).cursor@t(OrderID,Client,Amount)

  1. 如果想加快文件的读取速度,可以用多线程并行处理技术,只需简单地添加@m选项,代码即=file(“D: \\sOrder.txt”).cursor@tm(OrderID,Client,Amount)。不过由于多线程并行读入,这种用法将不能保证读入数据的次序。

  2. 有时候需要手工分段再并行计算,这时就要读入某一段文件,用代码可以实现:file(“D:\\sOrder.txt”).import@z@t(;,2:24)

  @z表示将文件按字节数大致分为24部分,只读取第2部分,集算器会自动取头补尾,以保证取出的数据是整行。

  如果分段后内存仍然装不下,可以将import函数改为cursor,即输出为游标。

按列宽读入文件

  文件data.txt无分隔符,如下:

esProc_java_retrieve_text_9

  需要按指定宽度读成4列的二维表,并输出到JAVA,id列取前3位,flag列取10-11位,d1列取14-24位,d2列取25-33位。如第1行的4列分别为:001、DT、100000000000、3210XXXX。

  集算器代码:

 A
1=file(“D:\\data.txt”).import@i()
2=A1.new(mid(~,1,3):id,mid(~,10,2):flag,mid(~,14,11):d1,mid(~,25,9):d2)

  A1:@i表示文件只有一列时返回为序列(集合)。

  A2:根据A1创建新二维表,mid函数可截取字符串,~表示每行数据。

  结果:

esProc_java_retrieve_text_11

文本含特殊字符

  文件data.csv含有引号,有些引号影响了数据的正常使用,现在要去掉引号再输出到JAVA,源数据如下:

esProc_java_retrieve_text_12

  集算器代码:

 A
1=file(“d:\\data.csv”).import(;”,”)
2=A1.new(replace(_1,”\”",”"):_1,replace(_2,”\”",”"):_2,
replace(_3,”\”",”"):_3,replace(_4,”\”",”"):_4)

  结果:

esProc_java_retrieve_text_14

文本含数学公式

  需要将文本中的公式解析成表达式,计算后再输出,源数据如下:

esProc_java_retrieve_text_15

  集算器代码:

 A
1=file(“D:\\equations.txt”).import@i()
2=As1.new(~:equations,eval(string(~)):result)

  函数eval可将字符串动态解析为表达式并执行。

  结果:

esProc_java_retrieve_text_17

多行记录
  下面文件每三行代表一条记录,比如第一条记录是:JFS        3       468.0        2009-08-13 39,现在需要将该文件输出成二维表。

esProc_java_retrieve_text_18

  集算器代码:

 A
1=file(“D:\\data.txt”).import@si()
2=A1.group((#-1)\3)
3=A2.new(~(1):OrderID, (line=~(2).array(“\t”))(1):Client,line(2):SellerId,line(3):Amount,~(3):OrderDate )

  先将文件读为序列,@s表示不拆分字段。再每三行分一组。”#”表示行号,“\”表示整除。最后根据每组结果创建新序表,~(1)表示当前组的第1个成员,函数array可将字符串拆分为序列,结果如下:

esProc_java_retrieve_text_21

  如果文件太大无法放入内存,应当用游标打开文件再分批计算。首先建立sub.dfx,作用是当有外部请求时就读入一批数据并返回,直到文件结束,代码如下:

 AB
1=file(“D:\\data.txt”).cursor@si()
2for A1,3000=A2.group((#-1)\3)
3 =B2.new(~(1):OrderID, (line=~(2).array(“\t”))(1):Client,line(2):SellerId,line(3):Amount,~(3):OrderDate )
4 result B3

  循环A1,每次读入3000条数据,并按照之前的算法处理。

  B4表示将B3传回主脚本。主脚本(也就是被JAVA调用的dfx文件)代码如下:

 A
1=pcursor(“sub.dfx”)

  函数pcursor可以从sub.dfx请求数据并转为游标输出。

不定行记录

  文件data.txt中每条记录属于不定的多个行,但每个字段都有其固定标记,分别是”Object Type:”、”left:”、”top ”、”Line Color: ”直到行末的文本,第1条记录即:Symbol1、14、11、RGB( 1 0 0 )。现在要将其读为结构化二维表。

esProc_java_retrieve_text_24

  集算器代码:

 A
1=file(“data.txt”).read()
2=A1.array(“Object Type: “).to(2,)
3=A2.new(~.array(“\r\n”)(1):OType,mid(~,s=pos(~,”left: “)+len(“left: “),pos(~,”\r\n”,s)-s):L,mid(~,s=pos(~,”top: “)+len(“top: “),pos(~,”\r\n”,s)-s):T,mid(~,s=pos(~,”Line Color: “)+len(“Line Color: “),if(r=pos(~,”\r\n”,s),r,len(~))-s+1):LColor)

 

  Read函数可将文件读为一个大字符串。之后用分隔符拆分字符串,去掉第一个空行。最后创建新序表,使用字符串函数array、pos、len、mid来找到所需字段。注意最后一行也许没有回车换行,因此要进行if判断。最终结果:

esProc_java_retrieve_text_27

  查找字段时使用了字符串函数,其实也可以用正则表达式。

  如果文件太大内存装不下,可以使用函数pcursor分批读取。

记录按标记分组

  文件data.txt按组存放记录,有list标记的是分组名(比如ARO、BDR、BSF),需要将分组名和组内字段拼在一起输出。源数据如下:

esProc_java_retrieve_text_28

  集算器代码:

 A
1=file(“mutiline2.txt”).import@si()
2=A1.group@i(like(~,”list:*”))
3=A2.conj(~.to(2,).new(mid(A2.~(1),6):Client,(t=~.array(“\t”))(1):c1,t(2):c2,t(3):c3,t(4):c4))

  先将文件读为字符串序列,再按照记录分隔标记分组,@i表示条件为真则分为新的一组,*是通配符。A2如下:

esProc_java_retrieve_text_31

  之后按序号取出字段,再合并各组记录,结果如下:

esProc_java_retrieve_text_32