利用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就可以了。
牛。好东西 "大佬提一点字符串加密解密的思路"
加盐是最简单的,其次要看密码学的东西,自己想的算法漏洞百出,不如直接学书里专家研究的成果 小伙子,明天来Oracle上班 增删改查的“查”,参数postion如何获取? c03xp 发表于 2020-8-13 10:14
增删改查的“查”,参数postion如何获取?
这个很容易实现,后续我会实现搜索功能 EnterpriseSolu 发表于 2020-8-13 09:01
"大佬提一点字符串加密解密的思路"
加盐是最简单的,其次要看密码学的东西,自己想的算法漏洞百出,不如 ...
好的,谢谢 最后的最后,将打包的jar包分享给大家,大家就可以直接引入工程使用 最后的最后,将打包的jar包分享给大家,大家就可以直接引入工程使用 楼主可以研究一下开源数据库 HSQLDB 的代码,如果要简化一下,不支持sql,那么sql解析器的部分可以跳过,但是物理存储部分的代码可以参考
页:
[1]
2