欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

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

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

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


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

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

id,username,password
1,abc,aaa
2,def,bbb
3,xyz,ccc

输入:文件路径和sql语句

  例:

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

输出:查询结果

  例:

1,abc,aaa
2,def,bbb
3,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("\n");
                }
            }
            
        }
        
        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,aaa
2,def,bbb
3,xyz,ccc

execute:select id from abc.csv 
1
2
3

execute:select id,username from abc.csv where id=2 
2,def

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

execute:select id,username from abc.csv where username=abc and password=bbb

 

完整程序请大家从下载

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

如有问题,大家来我的网站进行提问。

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

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