Java学习不走弯路教程(3.从文件内容查询开始) 2019-10-20

一. 前言在前两章教程中,分别介绍了DOS环境搭建和Eclipse环境搭建。本章将带大家实现用简单SQL语句查询文件。注:1.本文针对初学Java的同学训练学习思路,请不要太纠结于细节问题。2.本文旨在达到抛砖引玉的效果,希望大家扩展本例子,以学到更多知识的精髓。

二. 写给初学Java的同学在介绍本章内容之前,首先介绍一下Java的学习方法。相信大家在看本文的时候已经已经拿到了各种Java学习路径,大体都是一样。我想说的是,不要让知识的学习成为负担,Java技术种类繁多,是无论如何也学不完的。正确的学习方法是兴趣驱动,实例驱动。即通过一个简单的实例,不断加入所学知识进行扩展,最终扩展为一个大项目,达到系统学习,学以致用的效果。

三. 步入正题话不多说,大家自己理解,下面步入正题:

练习1.概要:本地有一个csv格式文件,用SQL语句查出结果。前提:本地有一个csv格式文件  例:abc.csv放在c:/temp文件夹下,内容如下:

id,username,password1,abc,aaa2,def,bbb3,xyz,ccc

输入:文件路径和sql语句

  例:

GetFile gf = new GetFile("c:/temp/");gf.queryFile("select * from abc.csv");

输出:查询结果

  例:

1,abc,aaa2,def,bbb3,xyz,ccc

请先自己动手想办法实现,实在做不出来再往下看,否则失去了练习的意义。

四. 实现步骤

首先,我们需要解析SQL语句。是的,标准的写法是把SQL转化成语法树(AST),然后再解析这颗语法树。但这篇文章面对的是初学者,我的目的是训练字符串的拆分,拼接,文件读取等基本操作,以及分析问题的方法。所以,把问题简单化。

首先确认程序功能的边界:下面是这个程序支持的最复杂的SQL语句(只支持单层的and条件):

select id,username from abc.csv where username=abc and password=aaa

所以,我们首先需要检查SQL的正确性:・必须包含select,from・可以包含where・且循序必须为select,from,where代码如下:

/** * @author http://www.java123.vip * @param sql * @return */ private boolean checkSql(String sql) { int selectPos = sql.indexOf("select"); int fromPos = sql.indexOf("from"); int wherePos = sql.indexOf("where"); if(selectPos != 0 || fromPos <= selectPos || (wherePos != -1 && wherePos <= fromPos)) { return false; }else { return true; } }

然后,我们需要把上述语句的如下元素解析出来:

查询项目:id,username查询文件:abc.csv查询条件:username=abc,password=aaa做一个类来存储解析结果:

package vip.java123.fileview;/** * * @author http://www.java123.vip * */public class SqlParseResult { public String[] fields; public String fileName; public String[] whereConditions; public void clearSpace() { for(int i = 0; i < fields.length; i ++) { fields[i] = fields[i].trim(); } fileName = fileName.trim(); for(int i = 0; i < whereConditions.length; i ++) { whereConditions[i] = whereConditions[i].trim(); } }}

 

解析的函数如下

/** * @author http://www.java123.vip * @param sql * @return */ private SqlParseResult parseSql(String sql) { int selectPos = sql.indexOf("select"); int fromPos = sql.indexOf("from"); int wherePos = sql.indexOf("where"); String columnStr = sql.substring(selectPos + "select".length(), fromPos).trim(); String fileNameStr; String whereStr; if(wherePos == -1) { fileNameStr = sql.substring(fromPos + "from".length()); whereStr = ""; }else { fileNameStr = sql.substring(fromPos + "from".length(),wherePos); whereStr = sql.substring(wherePos + "where".length()); } SqlParseResult spr = new SqlParseResult(); spr.fields = columnStr.split(","); spr.fileName = fileNameStr; if(wherePos == -1) { spr.whereConditions = new String[] {}; }else { spr.whereConditions = whereStr.split("and"); } spr.clearSpace(); return spr; }

 

(处理where后面的条件)接下来,对于读取的一行数据,我们需要检查该行数据是否符合查询条件,做个函数如下:header为第一行数据用逗号分割后的数组(文件头)

/** * @author http://www.java123.vip * @param line * @param whereConditions * @param header * @return */ private boolean checkRow(String line, String[] whereConditions, String[] header) { // username=abc password=aaa String[] lineColumns = line.split(","); for(int i = 0; i < whereConditions.length; i ++) { String key = whereConditions[i].split("=")[0]; String value = whereConditions[i].split("=")[1]; String checkValue = lineColumns[getHeaderIndex(header,key)]; if(!value.equals(checkValue)) { return false; } } return true; }

 

做个辅助函数,根据列名,返回列名的位置

/** * @author http://www.java123.vip * @param header * @param headerName * @return */ private int getHeaderIndex(String[] header,String headerName) { for(int i = 0; i < header.length; i ++) { if(header[i].equals(headerName)) { return i; } } return -1; }

 

(处理select后面的列名)如果数据符合查询条件,则根据select关键字后面的列名(fields)过滤查询结果

/** * @author http://www.java123.vip * @param line * @param fields * @param header * @return */ private String selectLine(String line, String[] fields, String[] header) { if(fields[0].equals("*")) { return line; } StringBuffer result = new StringBuffer(); String[] lineColumns = line.split(","); for(int i = 0; i < fields.length; i ++) { int columnIndex = this.getHeaderIndex(header, fields[i]); result.append(lineColumns[columnIndex]); if(i != fields.length -1) { result.append(","); } } return result.toString(); }

 

把上面的函数拼接在一起,主函数如下:

/** * @author http://www.java123.vip * @param sql * @return * @throws Exception */ public String queryFile(String sql) throws Exception{ sql = sql.toLowerCase().trim(); if(!checkSql(sql)) { return null; } SqlParseResult spr = parseSql(sql); File f = new File(basePath + spr.fileName); FileInputStream fis = new FileInputStream(f); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); boolean readHeader = true; String[] header = null; StringBuffer result = new StringBuffer(); String line = null; while((line = br.readLine()) != null) { if(readHeader) { header = line.split(","); readHeader = false; }else { if(checkRow(line,spr.whereConditions,header)) { result.append(selectLine(line,spr.fields,header)); result.append(""); } } } br.close(); isr.close(); fis.close(); return result.toString(); }

 

最后,测试我们的程序:

/** * @author http://www.java123.vip * @param args * @throws Exception */ public static void main(String[] args) throws Exception { GetFile gf = new GetFile("c:/temp/"); String sql1 = "select * from abc.csv "; String sql2 = "select id from abc.csv "; String sql3 = "select id,username from abc.csv where id=2 "; String sql4 = "select id,username from abc.csv where username=abc and password=aaa "; String sql5 = "select id,username from abc.csv where username=abc and password=bbb "; System.out.println("Execute:"+sql1); System.out.println(gf.queryFile(sql1)); System.out.println("Execute:"+sql2); System.out.println(gf.queryFile(sql2)); System.out.println("Execute:"+sql3); System.out.println(gf.queryFile(sql3)); System.out.println("Execute:"+sql4); System.out.println(gf.queryFile(sql4)); System.out.println("Execute:"+sql5); System.out.println(gf.queryFile(sql5)); }

 

输出结果如下:

Execute:select * from abc.csv 1,abc,aaa2,def,bbb3,xyz,cccExecute:select id from abc.csv 123Execute:select id,username from abc.csv where id=2 2,defExecute:select id,username from abc.csv where username=abc and password=aaa 1,abcExecute:select id,username from abc.csv where username=abc and password=bbb

 

完整程序请大家从[这里]下载

五.  后续本例为通过简单的SQL语句查询本地存在的文件,大家可以扩展此程序,让其支持更复杂的SQL,结果排序,索引等功能。后续章节我将在此程序的基础上,把CSV文件放到另外一台电脑,然后让其支持JDBC接口。最后换成数据库,并且一步一步实现ORM,Service,HTTP查询等功能。

如有问题,大家来我的网站进行提问。https://www.java123.vip/qa

版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。

原帖发表于:https://www.cnblogs.com/java123vip/p/9719828.html

Copyright © 2019 亚米游戏平台 All Rights Reserved
周昊
地址:浙江省乐清市柳市方桥路33号
全国统一热线:15809956490