从文件查询开始
一. 前言
在前两章教程中,分别介绍了DOS环境搭建和Eclipse环境搭建。
本章我们讲开始Java的代码学习。注:
1.本文针对初学Java的同学训练学习思路,点到为止,请不要太纠结于细节问题。2.本文旨在达到抛砖引玉的效果,希望大家扩展本例子,以学到更多知识的精髓。学习本章需要准备的知识:
1.读完本系列教程的前面章节。2.理解变量定义,赋值,函数,分支,循环,数组,ArrayList,HashMap,类和对象的基本概念及SQL查询的写法。3.理解文件的读取,字符串的常用操作。二. 步入正题
话不多说,大家自己理解,下面步入正题:
对于如下需求,大家想一下实现的方法:
概要:本地有一个Csv格式文件,用SQL语句查出Csv文件的内容。注:Csv文件可以理解为用逗号将字段分开的文件格式。例:abc.csv放在c:/temp文件夹下,内容如下:
id,username,password1,abc,aaa2,def,bbb3,xyz,ccc
对于如下SQL格式的语句查询出结果,比如:
select id,username from abc.csv where id=1
输出:
1,abc
三. 实现方法
首先分析这个需求的输入和输出,如下图所示:
我们需要将输入的SQL和CSV文件转化为查询结果。
首先我们需要解析SQL,把其中的关键因素提炼出来。标准的做法是把SQL转化成语法树(AST),然后再解析这颗语法树,如下图所示:
因为这篇文章的本意是通过这个例子熟悉字符串的操作,所以我用简单的方式来解析SQL。
首先定义程序功能的边界:下面是这个程序支持的最复杂的SQL语句(只支持单层的and条件):select id,username from abc.csv where username=abc and password=aaa
并且我定义了一个简单的规则来保证SQL的正确性:
・必须包含select,from・可以包含where・且循序必须为select,from,where我们来写一个函数按照上述规则检查SQL的正确性
代码如下:1 /** 2 * @author http://www.java123.vip 3 * @param sql 4 * @return 5 */ 6 private boolean checkSql(String sql) { 7 int selectPos = sql.indexOf("select"); 8 int fromPos = sql.indexOf("from"); 9 int wherePos = sql.indexOf("where");10 11 if(selectPos != 0 12 || fromPos <= selectPos13 || (wherePos != -1 && wherePos <= fromPos)) {14 return false;15 }else {16 return true;17 }18 }
然后,我们需要如下元素解析出来:
查询项目:id,username
查询文件:abc.csv查询条件:username=abc,password=aaa我们首先做一个类来存储上述元素:
1 package vip.java123.fileview; 2 3 /** 4 * 5 * @author http://www.java123.vip 6 * 7 */ 8 public class SqlParseResult { 9 public String[] fields;10 public String fileName;11 public String[] whereConditions;12 13 public void clearSpace() {14 for(int i = 0; i < fields.length; i ++) {15 fields[i] = fields[i].trim();16 }17 18 fileName = fileName.trim();19 20 for(int i = 0; i < whereConditions.length; i ++) {21 whereConditions[i] = whereConditions[i].trim();22 }23 }24 }
然后分别找到select,from,where的位置,并把它们之间的元素提取出来放入SqlParseResult中:
1 /** 2 * @author http://www.java123.vip 3 * @param sql 4 * @return 5 */ 6 private SqlParseResult parseSql(String sql) { 7 int selectPos = sql.indexOf("select"); 8 int fromPos = sql.indexOf("from"); 9 int wherePos = sql.indexOf("where");10 11 String columnStr = sql.substring(selectPos + "select".length(), fromPos).trim();12 String fileNameStr;13 String whereStr;14 if(wherePos == -1) {15 fileNameStr = sql.substring(fromPos + "from".length());16 whereStr = "";17 }else {18 fileNameStr = sql.substring(fromPos + "from".length(),wherePos);19 whereStr = sql.substring(wherePos + "where".length());20 }21 22 23 SqlParseResult spr = new SqlParseResult();24 spr.fields = columnStr.split(",");25 spr.fileName = fileNameStr;26 if(wherePos == -1) {27 spr.whereConditions = new String[] {};28 }else {29 spr.whereConditions = whereStr.split("and");30 }31 32 spr.clearSpace();33 34 return spr;35 }
因为select和where条件中包含数据的头信息(id,username,password),
所以我们需要在读取文件的时候,把这些头信息保存起来。用一个字符串数组来存储头信息(String[]),在读取文件的第一行时,把头信息存下来:String[] header = line.split(","); //line为一行数据我们做一个函数来读取制定头信息所在的列,用来定位该列上的数据:
1 /** 2 * @author http://www.java123.vip 3 * @param header 4 * @param headerName 5 * @return 6 */ 7 private int getHeaderIndex(String[] header,String headerName) { 8 for(int i = 0; i < header.length; i ++) { 9 if(header[i].equals(headerName)) {10 return i;11 }12 }13 14 return -1;15 }
接下来我们做一个函数来检查每一行数据(比如1,abc,aaa)是否符合where条件(比如id=1),
这个函数有三个参数,分别为:String line:一条数据(1,abc,aaa)String[] whereConditions:where条件(id=1)String[] header:文件头信息(id,username,password)我们根据这三个参数,返回一个检查结果(true或false)
1 /** 2 * @author http://www.java123.vip 3 * @param line 4 * @param whereConditions 5 * @param header 6 * @return 7 */ 8 private boolean checkRow(String line, String[] whereConditions, String[] header) { 9 // username=abc password=aaa10 String[] lineColumns = line.split(",");11 for(int i = 0; i < whereConditions.length; i ++) {12 String key = whereConditions[i].split("=")[0];13 String value = whereConditions[i].split("=")[1];14 15 String checkValue = lineColumns[getHeaderIndex(header,key)];16 if(!value.equals(checkValue)) {17 return false;18 }19 }20 return true;21 }
对于符合条件的数据,我们需要根据select的列名,返回制定列名的数据:
比如数据为1,abc,aaa,select语句为select id,username则返回1,abc函数代码如下:1 /** 2 * @author http://www.java123.vip 3 * @param line 4 * @param fields 5 * @param header 6 * @return 7 */ 8 private String selectLine(String line, String[] fields, String[] header) { 9 10 if(fields[0].equals("*")) {11 return line;12 }13 14 StringBuffer result = new StringBuffer();15 16 String[] lineColumns = line.split(",");17 for(int i = 0; i < fields.length; i ++) {18 int columnIndex = this.getHeaderIndex(header, fields[i]);19 result.append(lineColumns[columnIndex]);20 21 if(i != fields.length -1) {22 result.append(",");23 }24 }25 return result.toString();26 }
最后,我们做一个主函数,把上面的函数拼起来,
代码如下:1 /** 2 * @author http://www.java123.vip 3 * @param sql 4 * @return 5 * @throws Exception 6 */ 7 public String queryFile(String sql) throws Exception{ 8 sql = sql.toLowerCase().trim(); 9 10 if(!checkSql(sql)) {11 return null;12 }13 SqlParseResult spr = parseSql(sql);14 15 File f = new File(basePath + spr.fileName);16 17 FileInputStream fis = new FileInputStream(f);18 InputStreamReader isr = new InputStreamReader(fis);19 BufferedReader br = new BufferedReader(isr);20 21 boolean readHeader = true;22 String[] header = null;23 24 StringBuffer result = new StringBuffer();25 String line = null;26 while((line = br.readLine()) != null) {27 if(readHeader) {28 header = line.split(",");29 readHeader = false;30 }else {31 if(checkRow(line,spr.whereConditions,header)) {32 33 result.append(selectLine(line,spr.fields,header));34 result.append("\n");35 }36 }37 38 }39 40 br.close();41 isr.close();42 fis.close();43 44 return result.toString();45 }
四. 测试程序
最后,测试我们的程序:1 /** 2 * @author http://www.java123.vip 3 * @param args 4 * @throws Exception 5 */ 6 public static void main(String[] args) throws Exception { 7 8 GetFile gf = new GetFile("c:/temp/"); 9 10 String sql1 = "select * from abc.csv ";11 String sql2 = "select id from abc.csv ";12 String sql3 = "select id,username from abc.csv where id=2 ";13 String sql4 = "select id,username from abc.csv where username=abc and password=aaa ";14 String sql5 = "select id,username from abc.csv where username=abc and password=bbb ";15 16 System.out.println("Execute:"+sql1);17 System.out.println(gf.queryFile(sql1));18 19 System.out.println("Execute:"+sql2);20 System.out.println(gf.queryFile(sql2));21 22 System.out.println("Execute:"+sql3);23 System.out.println(gf.queryFile(sql3));24 25 System.out.println("Execute:"+sql4);26 System.out.println(gf.queryFile(sql4));27 28 System.out.println("Execute:"+sql5);29 System.out.println(gf.queryFile(sql5));30 31 }
输出结果如下:
Execute:select * from abc.csv 1,abc,aaa2,def,bbb3,xyz,cccExecute:select id from abc.csv 2Execute: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
完整程序请大家从[]下载
如有问题,大家来我的网站进行提问。
版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。