AItechnology 发表于 2020-8-12 23:13

利用ArrayList写一个简单的模拟数据库操作

这是纯技术交流的目的,欢迎各位点进来的大佬提出改进意见
首先,其实所有数据的存储不过就是转为字符串或者二进制形式存储,不外乎加一些加密,压缩,采用特殊编码格式等来存储,加密则是为了数据安全,压缩,特殊编码格式等则是为了节省存储空间,这里我就写一个简单的以字符串形式明文存储的仿数据库,优点就是实现简单,不需要学习sql语言操作数据库,适合存储临时,或者不需要保密的数据,当然,想安全的话,请各位大佬提一点字符串加密解密的思路,我会后续加进去,谢谢大家。缺点就是没有做过优化,肯能数据太多,比如几千万条,同时加载进入ArrayList,不知道内存吃紧不。所以后续想加一点加载超多一定数量的数据后进行优化的代码,希望各位大佬提点意见和思路。
废话不多说,我们都知道数据库基本功能就是增删查改,利用已经封装好的ArrayLsit可以很方便的实现数据库的基本功能,下面上代码:
public class MyOwnDateBase {
        //这是自定义数据库的底层实现,核心原理就是存储文本到这个文件中去
//下面是读取文本
private static ArrayList<String> getInfoFromTextfile(String filePath) {               
                ArrayList<String> list = new ArrayList<String>();
                String[] res=getFileName(filePath);
          try
          {
                String encoding = "UTF-8";             
                File file1 = new File(res);
                File file2 = new File(res);
                if(!file1.exists()) {
                        file1.mkdirs();
                }
                if (file2.isFile() && file2.exists())
                { // 判断文件是否存在
InputStreamReader read = new InputStreamReader(
                            new FileInputStream(file2), encoding);// 考虑到编码格式
BufferedReader bufferedReader = new BufferedReader(read);
                    String lineTxt = null;
                    while ((lineTxt = bufferedReader.readLine()) != null)
                    {
                      list.add(lineTxt);
                    }
                    bufferedReader.close();
                    read.close();
                }
                else
                {
                    file2.createNewFile();
                    System.out.println("初次使用,创建新的数据库,路经为:"+filePath);                                      
                }
          }
          catch (Exception e)
          {
                System.out.println("读取文件内容出错");
e.printStackTrace();
          }

          return list;

        }
        //下面是写入文本
private static void saveInfo2TextFile(String filePath,ArrayList<String> info) {
      FileWriter fw ;
                BufferedWriter bw;
                String[] res=getFileName(filePath);
                File file1 = new File(res);
      File file2 = new File(res);
      if(!file1.exists()) {
              file1.mkdirs();
      }
      try {
              if (file2.isFile() && file2.exists()) {

            }else {
                    file2.createNewFile();
                    System.out.println("初次使用,创建新的数据库,路经为:"+filePath);
            }

              if (file2.isFile() && file2.exists()) {
                      fw =new FileWriter(file2,false);
                      bw =new BufferedWriter(fw);
                      bw =new BufferedWriter(fw);
                      int num=info.size();
                      for(int i=0;i<num;i++) {
                              bw.write(info.get(i)+"\r\n");
                      }       
                      bw.flush();
                      bw.close();
                      fw.close();
              }else {
                            System.out.println("无法写入文件,数据库更新失败,可能是系统无此盘符");
                    }       
      }catch (Exception e) {
              e.printStackTrace();
                }finally {

                }

        }
        //由文本读取数据的进一步封装
static ArrayList<String> getDateFromDB(String pathOfDate) {
                ArrayList<String> reStrings=getInfoFromTextfile(pathOfDate);
                if(reStrings.isEmpty()) {
                        System.out.println("数据库为空");
                }
return reStrings;
        }
        //由文本写入的进一步封装
static void saveDate2DB(String pathOfDate,ArrayList<String> list) {
                saveInfo2TextFile(pathOfDate,list);
        }
        //处理文件路径的问题,路径请统一使用"/"来分隔,该函数自会处理
private static String[] getFileName(String str) {
                String[] tmpStrings=StringTools.seperateString(str, "/");
                String[] res=new String;
                str="test";
                String reString=tmpStrings;
                for(int i=1;i<tmpStrings.length-1;i++) {
                        reString=reString+File.separator+tmpStrings;
                }
                res=reString;
                String filename=reString+File.separator+tmpStrings;
                res=filename;
                return res;
        }
}

下面是一个工具类中字符串处理方法
public class StringTools {
        //parameter : str
        //the string you need to process
        //parameter : fenggefu
        //the seperate code in string, such as the "," in the string"Type=neme, Date=20200725"
        //for example: str="haha=haha,didi=didi"
        //res=StringTools.seperateString(str,",") will return an array res="haha=haha",res="didi=didi"
        public static String[] seperateString(String str,String fenggefu) {
                char fengefu=fenggefu.charAt(0);
                int len=str.length();
                char ss[]=str.toCharArray();
                int numberofCode=1;
                for(int i=0;i<len;i++) {
                        if(ss==fengefu) {numberofCode=numberofCode+1;}
                }
                String properties[];
                if(numberofCode>0) {
                        int tmpnum=0;
                        properties = new String;
                        for(int i=0;i<numberofCode;i++) {
                                properties="";
                        }
                        for(int i=0;i<len;i++) {
                                if(ss!=fengefu) {
                                        properties=properties+ss;
                                        }
                                if(ss==fengefu) {
                                        tmpnum=tmpnum+1;
                                        }
                        }
                }else {
                        properties = new String;
                        properties=str;
                }
                return properties;
        }
}
最后就是封装数据库的增删查改功能了:


import java.util.ArrayList;

import system.test.lvb.utils.StringTools;

public class SqlUtils {
        private static ArrayList<String> dateDBList;
        private static String PATHDB;
        private static Boolean isInitDB=false;
        //初始化数据库
public static void initSqlDB(String path) {
                PATHDB=path;
                dateDBList=MyOwnDateBase.getDateFromDB(PATHDB);
                isInitDB=true;
        }
        //插入数据
public static void insetDate(String info,int position) {
                if(isInitDB) {
                        if(position>=dateDBList.size()) {
                                dateDBList.add(info);
                        }else {
                                dateDBList.add(position, info);
                        }
                        commitDBInfo();
                }else {
                        System.out.println("未初始化数据库,编辑失败");
                }
        }
        //修改数据
public static void editDate(String info,int position) {
                if(isInitDB) {
                        if(position>=dateDBList.size()) {
                                System.out.println("索引越界,编辑失败");
                        }else {
                                dateDBList.remove(position);
                                dateDBList.add(position, info);
                        }
                        commitDBInfo();
                }else {
                        System.out.println("未初始化数据库,编辑失败");
                }
        }
        //添加数据
public static void addDate(String info) {
                if(isInitDB) {
                        dateDBList.add(info);
                        commitDBInfo();
                }
                else {
                        System.out.println("未初始化数据库,编辑失败");
                }
        }
        //保存数据
private static void commitDBInfo() {
                if(isInitDB)       
                MyOwnDateBase.saveDate2DB(PATHDB, dateDBList);
        }
        //删除数据
public static void delDate(int position) {
                if(isInitDB)
                if(dateDBList.size()<position) {
                        System.out.println("索引越界,删除失败");
                }else {
                        dateDBList.remove(position);
                        commitDBInfo();
                }
        }
        //清空数据
public static void clearDate() {
                if(isInitDB)
                if(dateDBList.size()>0) {
                        dateDBList.clear();
                        commitDBInfo();
                }
        }
        //获取记录
public static String getDate(int postion) {
                if(isInitDB)
                if(dateDBList.size()>0&&dateDBList.size()>postion) {
                        return dateDBList.get(postion);
                }else {
                        return "null";
                }
                return "null";
        }
        //获取记录数目
public static int getSize() {
                if(isInitDB)
                return dateDBList.size();
                return 0;
}
        //获取整个数据库
public static void getAllDate(ArrayList<String> info) {
                for(int i=0;i<dateDBList.size();i++) {
                        info.add(dateDBList.get(i));
                }
        }
        //保存所有数据
public static void saveAllDate(ArrayList<String> info) {
                ArrayList<String> tmpArrayList=new ArrayList<String>();
                ArrayList<String> finalArrayList=new ArrayList<String>();
getAllDate(tmpArrayList);
                for(int i=0;i<info.size();i++) {
                        tmpArrayList.add(info.get(i));//新旧数据合并
}
finalArrayList=StringTools.getSingle(tmpArrayList);//清除冗余重复数据,如果不用管数据库中数据是否重复,这句代码可以删了
clearDate();//清空数据库
for(int i=0;i<finalArrayList.size();i++) {
                        addDate(finalArrayList.get(i));//重新存储数据
}
        }
}

最后,再加上前面那个工具类StringTools中另一个方法的实现:
public static ArrayList<String> getSingle(ArrayList<String> list){
      ArrayList<String> newList = new ArrayList<String>();    //1.创建新集合
Iterator<String> it = list.iterator();          //2.根据传入的集合(老集合)获取迭代器
while(it.hasNext()){                  //3.遍历老集合
String obj = it.next();             //记录住每一个元素
if(!(newList.contains(obj))){       //如果新集合中不包含老集合中的元素
newList.add(obj); //将该元素进行添加
}
      }
return newList;
    }
至此,完成模拟数据库基本功能的增删查改等功能。最后就是贴具体调用的方式(只是我的工程中一段代码调用):
//提取网址头       
ArrayList<String> finalReStrings=new ArrayList<String>();
                ArrayList<String> singleReStrings=new ArrayList<String>();
                for(int i=0;i<filePath.size();i++) {
                        String[] strings=StringTools.seperateString(filePath.get(i), "/");
                        finalReStrings.add(strings+"//"+strings);
                        System.out.println(filePath.get(i));
                }
                //保存在数据库
singleReStrings=StringTools.getSingle(finalReStrings);
                SqlUtils.initSqlDB("C:/test/website1.txt");
                SqlUtils.saveAllDate(singleReStrings);
最后的最后,将打包的jar包分享给大家,大家就可以直接引入工程使用了.
由于论坛不支持jar文件,所以我改后缀为rar,大家到时候直接把后缀改为jar就可以了。

zguozzao 发表于 2020-8-13 08:01

牛。好东西

EnterpriseSolu 发表于 2020-8-13 09:01

"大佬提一点字符串加密解密的思路"

加盐是最简单的,其次要看密码学的东西,自己想的算法漏洞百出,不如直接学书里专家研究的成果

狂龙@ 发表于 2020-8-13 09:45

小伙子,明天来Oracle上班

c03xp 发表于 2020-8-13 10:14

增删改查的“查”,参数postion如何获取?

AItechnology 发表于 2020-8-13 12:13

c03xp 发表于 2020-8-13 10:14
增删改查的“查”,参数postion如何获取?

这个很容易实现,后续我会实现搜索功能

AItechnology 发表于 2020-8-13 13:06

EnterpriseSolu 发表于 2020-8-13 09:01
"大佬提一点字符串加密解密的思路"

加盐是最简单的,其次要看密码学的东西,自己想的算法漏洞百出,不如 ...

好的,谢谢

zyfhyc 发表于 2020-8-22 23:22

最后的最后,将打包的jar包分享给大家,大家就可以直接引入工程使用

zyfhyc 发表于 2020-8-22 23:23

最后的最后,将打包的jar包分享给大家,大家就可以直接引入工程使用

bookaccount 发表于 2020-8-23 03:21

楼主可以研究一下开源数据库 HSQLDB 的代码,如果要简化一下,不支持sql,那么sql解析器的部分可以跳过,但是物理存储部分的代码可以参考
页: [1] 2
查看完整版本: 利用ArrayList写一个简单的模拟数据库操作