Java 中如何查询计算 txt/csv?
Github上有很多类库都能解析txt/csv,之后可以让Hibernate写入数据库,或手工拼出insert语句入库,最后用数据库查询。这种方法可以利用SQL的强大计算能力,但结构太复杂,时效性更是差得离谱。结构简单且时效性强的工具也有,其中Tablesaw模仿了Python Pandas,CSVJDBC可以在文件上直接执行类SQL语句,可惜这两种工具都不成熟,很多基本计算还不支持。
既有强大计算能力,又能直接计算文件的JAVA开源库,集算器SPL是个更好的选择。
SPL可通过JDBC接口被调用,入门毫无难度。比如对txt文件里的订单分组汇总:
…
Class.forName("com.esproc.jdbc.InternalDriver");
Connection connection =DriverManager.getConnection("jdbc:esproc:local://");
Statement statement = connection.createStatement();
String str="=T(\"D:/data/Orders.txt\").groups(year(OrderDate);sum(Amount))";
ResultSet result = statement.executeQuery(str);
…
SPL提供了丰富的库函数,可直接完成常见的查询计算,比如:
条件查询
str="T(\"D:/data/Orders.txt\").select(Amount>1000 && Amount<=3000 && like(Client,\"*S*\"))
排序
str ="=T(\"D:/data/Orders.txt\").sort(Client,-Amount)";
去重
str="=T(\"D:/data/Orders.txt\").id(Client)";
分组汇总
str ="=T(\"D:/data/Orders.txt\").groups(year(OrderDate);sum(Amount))";
关联
str ="=join(T (\"D:/data/Orders.txt\"):O,SellerId; T(\"D:/data/Employees.txt\"):E,EId).new(O.OrderID,O.Client,O.SellerId,O.Amount,O.OrderDate, E.Name,E.Gender,E.Dept)";
SPL还支持SQL语法,可降低数据库程序员的学习成本。比如上面的分组汇总可以写作:
str="$SELECT year(OrderDate),sum(Amount) from D:/data/Orders.txt group by year(OrderDate)"
SPL支持算法外置,修改算法时无需编译代码,适合较复杂或频繁修改的计算,可显著降低耦合性。比如:在各部门找出比本部门平均年龄小的员工。先将SPL算法存为脚本文件:
A |
|
1 |
=T("Employee.csv") |
2 |
=A1.group(DEPT; (a=~.avg(age(BIRTHDAY)),~.select(age(BIRTHDAY) |
3 |
=A2.conj(YOUNG) |
再在JAVA代码中以存储过程的方式调用脚本文件:
…
Class.forName("com.esproc.jdbc.InternalDriver");
Connection connection =DriverManager.getConnection("jdbc:esproc:local://");
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("call getYoung()");
...
上面是日常工作中常见的计算,还有些计算不常见,但遇到了就很头疼,好在SPL有方便的函数和灵活的语法,可轻松解决各类疑难杂症。
SPL可解析各类特殊分隔符,用法简单直观。比如csv文件以双横线--为分隔符,对该文件进行条件查询:
= file("D:/Orders.txt").import@t(;,"--").select(Amount>1000 && Amount<=3000)
SPL可解析不规则的文本,代码也不难。比如某文件三行对应一条记录,其中第二行还包含多个字段,将该文件整理成规范的二维表,并按第3和第4个字段排序:
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 ) |
4 |
=A3.sort(_3,_4) |
有些计算逻辑较为复杂,即使存储过程也难以实现,而SPL计算能力强大,可轻松解决此类问题。比如:商品在出库\入库时,日期上通常不连续,要据此计算出多种商品在指定的连续日期内的库存情况。SPL只需短短几行代码:
A |
|
1 |
=file("d:/inout.txt").import@t() |
2 |
=periods(argBeginDate,argEndDate) |
3 |
=A1.group(product;~.align(A2,date):g) |
4 |
=A3.news(g;A3.product,A2(#):date,ifn(in,0):in, ifn(out,0):out, stock[-1]+in-out:stock) |
SPL提供了专业的IDE,不仅有完整的调试,还能用表格的形式观察每一步的中间计算结果,特别适合设计逻辑复杂的计算:
SPL还支持Excel、XML、数据库、NoSQL、restful等数据源,支持大文件高性能计算,诸多特性无法一一展开详述。
英文版