C语言【微项目17】—DustBase微尘数据库[自制键值对数据库][超轻量]【2022-03-23】

C语言【微项目17】—DustBase微尘数据库[自制键值对数据库][超轻量]【2022-03-23】

  • 1. DustBaseShell.c
  • 2. DustBaseCore.c
  • 3. DustBaseShell模式使用截图
  • 4. DustBase典型使用流程
  • 5. DustBaseCore嵌入式使用
  • 6. DustBaseShell模式运行视频

【TDTX】
【C99】
【编译与运行环境】64位Windows操作系统,TDM-gcc 4.9.2 64bit(-std=c99)编译

项目Gitee仓库】DustBase,同时将V1.0版本也放在C语言-微项目。

【介绍】微尘数据库,一个十分简单轻量的非关系型——键值对数据库,纯C语言实现。

【使用方式】

  1. 由DustBaseShell.exe命令行交互式使用。由“.”前缀调用命令、由“$”前缀调用函数。(已实现
  2. 嵌入式使用。将DustBaseCore.c通过#include "DustBaseCore.c"的方式直接将数据库编译到用户程序中去。(已实现)
  3. 连接式用法。(待定)

【功能】
1.支持的函数

函数 作用
createDataBase 创建数据库
usingDataBase 指定要使用的数据库
clearUsingDataBase 清除使用中的数据库
deleteDataBase 删除某个未使用中的数据库
putString 存入键值对
deleteString 删除键值对
getString 获取键的值
setKeyValue 更改键的值
getKeyList 获取键名的列表

2.使用方法

  • 在DustBaseShell.exe命令行交互式环境中,使用’.'开头可以使用Shell里面的命令
  • 在DustBaseShell.exe命令行交互式环境中,使用’$'开头可以使用上述支持的函数里面的命令
  • 设置好环境变量后,DustBaseShell.exe支持带参启动!
  • 在嵌入式使用方法中,直接调用上述支持的函数即可

【版本】version 1.0

1. DustBaseShell.c

#include 
#include 
#include 
#include 
#include "DustBaseCore.c"
char c;
int count = 0;


int isLegalparameter(char c)
{
	//判断参数是不是合法参数字符 
	if(c >= '0' && c <= '9')
	{
		return 1;
	}
	if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
	{
		return 1;
	}
	return 0;
}

int checkParameter(char* command,int parastart,char** para)
{
	//command是用户输入的字符串
	//parastart是可能的函数参数起始位置
	//para将会指向合法的参数起始位置
	//检查单参数函数 
	int flag = 0;
	for(int i = parastart;i < strlen(command);i++)
	{
		if(flag == 0 && command[i] != ' ' && isLegalparameter(command[i]))
		{
			//过滤参数字符串的非法前缀 
			parastart = i;
			flag = 1;
			continue;	
		}
		if(flag == 1 && !isLegalparameter(command[i]))
		{
			//找到非空参数起始位置后,检查字符合法性 
			*para = NULL;
			return 0;
		}
	} 
	//printf("start = %d\n",parastart);
	*para = &command[parastart];
	return 1;
}

int checkTwoParameter(char* command,int parastart,char** ppkey,char** ppvalue)
{
	int secondparastart = -1;
	int flag = 0;
	for(int i = parastart;i < strlen(command);i++)
	{
		//判断该参数字符串有没有空格,即是否可能输入了两个参数,而非一个 
		if(flag == 0 && command[i] != ' ')
		{
			flag = 1;
		}
		if(flag == 1 && command[i] == ' ' && i + 1 < strlen(command))
		{
			command[i] = '\0';
			secondparastart = i+1;
		}
	}
	if(secondparastart == -1)
	{
		return 0;
	}
	
	//puts(&command[parastart]);
	//puts(&command[secondparastart]);
	int result = 0;
	result = checkParameter(command,parastart,ppkey);
	*ppvalue = &command[secondparastart];
	for(int i = 0;i < strlen(*ppvalue);i++)
	{
		if((*ppvalue)[i] == '$')
		{
			return 0;
		}
	}
	return result;
}

void printHello()
{
	puts("Welcome to DustBase v1.0.0.");
	puts("This is a very very lite datastore!");
	puts("Two type '.' and '$',$ use to function.");
	puts("Say \".help\" for more information.");
}
void printHelp()
{
	puts(".help                   Print this help message");
	puts(".databases              List names and files of attached databases");
	puts(".function               List supported features");
	puts(".this                   Introduce the DustBase");
	puts(".cls                    Clear screen");
	puts(".restart                Restart DustBaseShell");
	puts(".quit                   Quit the DustBaseShell");
	puts("$function parameter     For example:$createDataBase helloworld");
}
void printFunction()
{
	puts("----------------------+---------------------------------------"); 
	puts("|createDataBase       |-创建数据库                           |");
	puts("----------------------+---------------------------------------");
	puts("|usingDataBase        |-指定要使用的数据库                   |");
	puts("----------------------+---------------------------------------");
	puts("|clearUsingDataBase   |-清除使用中的数据库                   |");
	puts("----------------------+---------------------------------------");
	puts("|deleteDataBase       |-删除某个未使用中的数据库             |");
	puts("----------------------+---------------------------------------");
	puts("|putString            |-存入键值对                           |");
	puts("----------------------+---------------------------------------");
	puts("|deleteString         |-删除键值对                           |");
	puts("----------------------+---------------------------------------");
	puts("|getString            |-获取键的值                           |");
	puts("----------------------+---------------------------------------");
	puts("|setKeyValue          |-更改键的值                           |");
	puts("----------------------+---------------------------------------");
	puts("|getKeyList           |-获取键名的列表                       |");
	puts("----------------------+---------------------------------------");
	puts("|getKeySeekIndex      |-获取[键的索引位置及键名组合]的列表   |");
	puts("----------------------+---------------------------------------");
}
void printIntroduce()
{
	puts("- DustBase,微尘数据库!");
	puts("- 一个十分简单轻量的非关系型——键值对数据库,纯C语言实现!");
	puts("- 作者:CSDN/Gitee:TDTX/TDTXYZHH");
}
int main(int argc,char*argv[])
{
	printHello();
	
	if(argc >= 2)
	{
		if(argv[1] != NULL && !strcmp(".help",argv[1]))
		{
			printf("DB> %s\n",argv[1]);
			printHelp();
		}
		if(argv[1] != NULL && !strcmp(".function",argv[1]))
		{
			printf("DB> %s\n",argv[1]);
			printFunction();
		}
		if(argv[1] != NULL && !strcmp(".this",argv[1]))
		{
			printf("DB> %s\n",argv[1]);
			printIntroduce();
		}
		if(argv[1] != NULL && !strcmp(".quit",argv[1]))
		{
			printf("DB> %s\n",argv[1]);
			return 0;
		}
	}

	
	//puts("");
	while(1)
	{
		printf("DB> ");
		while(1)
		{
			c = fgetc(stdin);
			if(c == '\n')
			{
				break;
			}	
			if(c == '.' && ftell(stdin) == 1)
			{
				int commandsize = 0;
				char* command = (char*)malloc(0);	
				while(1)
				{
					c = fgetc(stdin);
					command = (char*)realloc(command,sizeof(char)*(commandsize + 1));
					commandsize++;
					
					if(c == '\n')
					{
						command[commandsize - 1] = '\0';
						break;
					}
					command[commandsize - 1] = c;
				}
				if(!strcmp("help",command))
				{
					printHelp();
					free(command);
					break;
				}
				else if(!strcmp("databases",command))
				{
					//puts("teset=====");
					DIR* dir = NULL;
					struct dirent* dt;
					int i = 0;
					dir = opendir("./");
					int flag = 0;
					puts("=====[In this folder]=====");
					while(dt = readdir(dir))
					{
						//print("hello");
						
						//printf("i = %d\n",i);
						char* filename = &(dt->d_name)[strlen(dt->d_name) - 4];
						if(!strcmp(filename,".tdb"))
						{
							i++;
							printf("->%2d:%s\n",i,dt->d_name);
							flag = 1;
						}
					}
					if(flag == 0)
					{
						puts("Info:NO DATABASE[.tdb]");
					}
					puts("=====[In this folder]=====");
					closedir(dir);
					free(command);
					break;
				}
				else if(!strcmp("function",command))
				{
					printFunction(); 
					free(command);
					break;
				}
				else if(!strcmp("this",command))
				{
					printIntroduce();
					free(command);
					break;
				}
				else if(!strcmp("cls",command))
				{
					system("cls");
					free(command);
					break;
				}
				else if(!strcmp("restart",command))
				{
					char* t[] = {"DustBase",NULL};
					main(0,t);
					free(command);
					exit(0);
					break;
				}
				else if(!strcmp("quit",command))
				{
					free(command);
					return 0;
				}
				free(command);
				break;
			}
			else if(c == '$' && ftell(stdin) == 1)
			{
				int commandsize = 0;
				char* command = (char*)malloc(0);	
				while(1)
				{
					c = fgetc(stdin);
					command = (char*)realloc(command,sizeof(char)*(commandsize + 1));
					commandsize++;
					
					if(c == '\n')
					{
						command[commandsize - 1] = '\0';
						break;
					}
					command[commandsize - 1] = c;
				}
				
				if(strstr(command,"createDataBase") != NULL)
				{
					puts("create");
					if(strlen(command) > 15)
					{
						if(command[14] != ' ')
						{
							puts("Function:createDataBase input error,need space between function and parameter!");
						}
						else
						{
							char* parameter = &command[15];
							int i = checkParameter(command,15,&parameter);
							if(i == 0)
							{
								puts("Function:createDataBase input error,parameters have illegal parameter!");
							}
							else
							{
								puts(parameter);
								createDataBase(parameter);
							}	
						}
					}
					else
					{
						puts("Function:createDataBase input error,need parameter!");
					}

					free(command);
					break;
				}
				else if(strstr(command,"usingDataBase") != NULL)
				{
					puts("use");
					if(strlen(command) > 14)
					{
						if(command[13] != ' ')
						{
							puts("Function:createDataBase input error,need space between function and parameter!");
						}
						else
						{
							char* parameter = &command[14];
							int i = checkParameter(command,14,&parameter);
							if(i == 0)
							{
								puts("Function:createDataBase input error,parameters have illegal parameter!");
							}
							else
							{
								puts(parameter);
								usingDataBase(parameter);
							}	
						}
					}
					else
					{
						puts("Function:createDataBase input error,need parameter!");
					}
					free(command);
					break;
				}
				else if(strstr(command,"clearUsingDataBase") != NULL)
				{
					puts("clearusing");
					if(strlen(command) == 18)
					{
						clearUsingDataBase();
					}
					else
					{
						puts("Function:createDataBase input error,don't need parameter!");
					}
					free(command);
					break;
				}
				else if(strstr(command,"deleteDataBase") != NULL)
				{
					puts("deleteDataBase");
					if(strlen(command) > 15)
					{
						if(command[14] != ' ')
						{
							puts("Function:deleteDataBase input error,need space between function and parameter!");
						}
						else
						{
							char* parameter = &command[15];
							int i = checkParameter(command,15,&parameter);
							if(i == 0)
							{
								puts("Function:deleteDataBase input error,parameters have illegal parameter!");
							}
							else
							{
								puts(parameter);
								deleteDataBase(parameter);
							}	
						}
					}
					else
					{
						puts("Function:deleteDataBase input error,need parameter!");
					}
					free(command);
					break;
				}
				else if(strstr(command,"putString") != NULL)
				{
					puts("putString");
					if(strlen(command) > 10)
					{
						if(command[9] != ' ')
						{
							puts("Function:putString input error,need space between function and parameter!");
						}
						else
						{
							char* pkey = &command[10];
							
							char* pvalue = NULL;
							int result = checkTwoParameter(command,10,&pkey,&pvalue);
							if(result == 0)
							{
								puts("Function:putString input error,parameters have illegal parameter!");
							}
							else
							{
								//puts(pkey);
								//puts(pvalue);
								putString(pkey,pvalue);
							}	
						}
					}
					else
					{
						puts("Function:putString input error,need parameter!");
					}
					free(command);
					break;
				}
				else if(strstr(command,"deleteString") != NULL)
				{
					puts("deleteString");
					if(strlen(command) > 13)
					{
						if(command[12] != ' ')
						{
							puts("Function:deleteString input error,need space between function and parameter!");
						}
						else
						{
							char* parameter = &command[13];
							int i = checkParameter(command,13,&parameter);
							if(i == 0)
							{
								puts("Function:deleteString input error,parameters have illegal parameter!");
							}
							else
							{
								puts(parameter);
								deleteString(parameter);
							}	
						}
					}
					else
					{
						puts("Function:deleteString input error,need parameter!");
					}
					free(command);
					break;
				}
				else if(strstr(command,"getString") != NULL)
				{
					puts("getString");
					if(strlen(command) > 10)
					{
						if(command[9] != ' ')
						{
							puts("Function:getString input error,need space between function and parameter!");
						}
						else
						{
							char* pkey = &command[10];
							
							char* pvalue = NULL;
							int result = checkTwoParameter(command,10,&pkey,&pvalue);
							if(result == 0)
							{
								puts("Function:getString input error,parameters have illegal parameter!");
							}
							else
							{
								//puts(pkey);
								//puts(pvalue);
								//char* svalue = getString(pkey,pvalue);
								//puts(svalue);
								getString(pkey,pvalue);
							}	
						}
					}
					else
					{
						puts("Function:getString input error,need parameter!");
					}
					free(command);
					break;
				}
				else if(strstr(command,"setKeyValue") != NULL)
				{
					puts("setKeyValue");
					if(strlen(command) > 12)
					{
						if(command[11] != ' ')
						{
							puts("Function:setKeyValue input error,need space between function and parameter!");
						}
						else
						{
							char* pkey = &command[12];
							
							char* pvalue = NULL;
							int result = checkTwoParameter(command,12,&pkey,&pvalue);
							if(result == 0)
							{
								puts("Function:setKeyValue input error,parameters have illegal parameter!");
							}
							else
							{
								//puts(pkey);
								//puts(pvalue);
								setKeyValue(pkey,pvalue);
							}	
						}
					}
					else
					{
						puts("Function:setKeyValue input error,need parameter!");
					}
					free(command);
					break;
				}
				else if(strstr(command,"getKeyList") != NULL)
				{
					puts("getKeyList");
					if(strlen(command) == 10)
					{
						struct keylistinfo* keys = getKeyList();
						if(keys != NULL)
						{
							for(int i = 0;i < keys->n;i++)
							{
								if(i == 0)
								{
									printf("[\"%s\"",(keys->keylist)[i]);
								}
								else
								{
									printf(",\"%s\"",(keys->keylist)[i]);
								}
								if(i == keys->n - 1)
								{
									printf("]\n");
								}
							}	
						}
					}
					else
					{
						puts("Function:createDataBase input error,don't need parameter!");
					}
					free(command);
					break;
				}
				free(command);
				break;
			}
		}
	}
	
	system("pause");
	return 0;
}

2. DustBaseCore.c

#include 
#include 
#include 

struct keylistinfo
{
	char** keylist;
	int n;
};
char rundatabasename[37] = {'\0'};//数据库名最多32字符 
char* value = NULL;
struct keylistinfo* keys = NULL;

int connecDataBase();//待定
int disconnectDataBase();//待定

int createDataBase(char* databasename);
int usingDataBase(char* databasename);
int clearUsingDataBase();
int deleteDataBase(char* databasename);
int putString(char* key,char* value);
int deleteString(char* key);
char* getString(char* key,char* error);
int setKeyValue(char* key,char* newvalue);
struct keylistinfo* getKeyList();

int getKeySeekIndex();//暂不实现 


int connecDataBase()
{
	//待定 
}
int disconnectDataBase()
{
	//待定 
}
 

int createDataBase(char* databasename)
{
	int len = strlen(databasename);
	if(len > 32)
	{
		puts("Warning:the length of database name exceeds the limit(32)");
		return 0;
	}
	
	char name[len+5];
	strcpy(name,databasename);
	name[len] = '.';
	name[len+1] = 't';
	name[len+1+1] = 'd';
	name[len+1+1+1] = 'b';
	name[len+1+1+1+1] = '\0';
	//puts(name);

	if(!access(name,F_OK))
	{
		puts("Error:the newdatabase exist!");
		return -1;
	}

	FILE* database = fopen(name,"a");
	if(database == NULL)
	{
		puts("Error:create database fail!");
		return -1;
	}
	fflush(database);
	fclose(database);
	
	puts("Info:create database success!");
	
	return 1;
}

int usingDataBase(char* databasename)
{
	int len = strlen(databasename);
	if(len > 32)
	{
		puts("Warning:the length of database name exceeds the limit(32)");
		return 0;
	}
	
	char name[len+5];
	strcpy(name,databasename);
	name[len] = '.';
	name[len+1] = 't';
	name[len+1+1] = 'd';
	name[len+1+1+1] = 'b';
	name[len+1+1+1+1] = '\0';
	//puts(name);
	
	if(access(name,F_OK))
	{
		puts("Error:the database doesn't exist!");
		return -1;
	}
	
	strcpy(rundatabasename,name);
	puts("Info:using database success!");
	
	char* value = (char*)malloc(0);
	
	keys = (struct keylistinfo*)malloc(sizeof(struct keylistinfo));
	keys->n = 0;
	keys->keylist = (char**)malloc(0);
	
	return 1;
}


int clearUsingDataBase()
{
	if(strlen(rundatabasename) == 0)
	{
		puts("Error:clear using databse fail,no database is using!");
		return 0;
	}
	rundatabasename[0] = '\0';
	
	free(value);
	value = NULL;
	
	for(int i = 0;i < keys->n;i++)
	{
		free((keys->keylist)[i]);
	} 
	free(keys->keylist);
	free(keys);
	keys = NULL;
	
	puts("Info:clear using databse success!");
	return 1;
}


int deleteDataBase(char* databasename)
{
	int len = strlen(databasename);
	if(len > 32)
	{
		puts("Warning:the length of database name exceeds the limit(32)");
		return 0;
	}
	
	char name[len+5];
	strcpy(name,databasename);
	name[len] = '.';
	name[len+1] = 't';
	name[len+1+1] = 'd';
	name[len+1+1+1] = 'b';
	name[len+1+1+1+1] = '\0';
	//puts(name);
	
	if(access(name,F_OK))
	{
		puts("Error:the newdatabase doesn't exist!");
		return -1;
	}
	
	if(!strcmp(rundatabasename,name))
	{
		puts("Warning:the database is using,can not delete!");
		return 0;
	}
	
	if(remove(name) != 0)
	{
		puts("Error:delete databse fail!");
		return -1;
	}

	puts("Info:delete databse success!");
	return 1;
}

int putString(char* key,char* value)
{
	if(rundatabasename[0] == '\0')
	{
		puts("Error:no database is using!");
		return -1;
	}
	if(strlen(key) > 32)
	{
		puts("Warning:the length of key exceeds the limit(32)");
		return 0;
	}
	//puts(rundatabasename);
	for(int i = 0; i < strlen(value);i++)
	{
		if(value[i] == '$')
		{
			puts("Warning:the value can not contain '$'!");
			return 0;
		}
	}
	FILE* database = fopen(rundatabasename,"a+");
	if(database == NULL)
	{
		puts("Error:the database doesn't exist!");
		return -1;
	}
	
	char tkey[33];
	int cancopy = 0;
	int k = 0;
	char tc;
	while(1)
	{
		//这里用来判断里面有没有该key,如果存在则不存入,没有则存入 
		tc = fgetc(database);
		if(tc == EOF)
		{
			break;
		}
		if(tc == '$')
		{
			cancopy = 1;
			continue;
		}
		if(cancopy == 1)
		{
			if(tc == ':')
			{
				tkey[k] = '\0';
				k = 0;
				cancopy = 0;
				//puts(tkey);
				if(!strcmp(key,tkey))
				{
					fclose(database);
					puts("Error:the key exists!");
					return -1;
				}
				tkey[0] = '\0';
			}
			else
			{
				tkey[k++] = tc;
				continue;
			}
		}
	}
	
	fprintf(database,"$%s:%s\n",key,value);
	fflush(database);
	fclose(database);
	
	puts("Info:putString success!");
	return 1;
}

int deleteString(char* key)
{
	if(rundatabasename[0] == '\0')
	{
		puts("Error:no database is using!");
		return -1;
	}
	if(strlen(key) > 32)
	{
		puts("Warning:the length of key exceeds the limit(32)");
		return 0;
	}
	//puts(rundatabasename);
	FILE* database = fopen(rundatabasename,"a+");
	if(database == NULL)
	{
		puts("Error:the database doesn't exist!");
		return -1;
	}
	
	char tkey[33];
	int cancopy = 0;
	int k = 0;
	char tc;
	int havekey = 0;
	int location = 0;
	while(1)
	{
		//这里用来判断里面有没有该key,如果存在则执行删除,不存在则返回-1 
		tc = fgetc(database);
		if(tc == EOF)
		{
			break;
		}
		if(tc == '$')
		{
			location = ftell(database);
			cancopy = 1;
			continue;
		}
		if(cancopy == 1)
		{
			if(tc == ':')
			{
				tkey[k] = '\0';
				k = 0;
				cancopy = 0;
				//puts(tkey);
				if(!strcmp(key,tkey))
				{
					havekey = 1;
					//puts("Error:the key exists!");
					break;
				}
				tkey[0] = '\0';
			}
			else
			{
				tkey[k++] = tc;
				continue;
			}
		}
	}
	
	if(havekey == 1)
	{
		int flag = 0;
		fseek(database,0,SEEK_SET);//将文件指针定位到起始位置
		
		FILE* temp = fopen("temp.tdb","w");
		if(temp == NULL)
		{
			puts("Error:new temp-database fail!");
			fclose(database);
			return -1;	
		}
		while(1)
		{
			tc = fgetc(database);
			if(tc == EOF)
			{
				break;
			}
			if(ftell(database) == location)
			{
				flag = 1;
			}
			if(flag == 1)
			{
				if((tc == '$' || tc == EOF) && ftell(database) > location)
				{
					flag = 0;
					fputc(tc,temp);

				}
			}
			else
			{
				fputc(tc,temp);
			}
		}
		fclose(database);
		fclose(temp);
		
		remove(rundatabasename);
		rename("temp.tdb",rundatabasename);
		
		puts("Info:delete key-value success!");
		return 1;
	}
	else
	{
		fclose(database);
		puts("Error:the key doesn't exists,cannot delete key-vlaue!");
		return 0;
	}
}

char* getString(char* key,char* error)
{
	if(rundatabasename[0] == '\0')
	{
		puts("Error:no database is using!");
		return error;
	}
	if(strlen(key) > 32)
	{
		puts("Warning:the length of key exceeds the limit(32)");
		return error;
	}
	//puts(rundatabasename);
	FILE* database = fopen(rundatabasename,"a+");
	if(database == NULL)
	{
		puts("Error:the database doesn't exist!");
		return error;
	}
	
	char tkey[33];
	int cancopy = 0;
	int k = 0;
	char tc;
	int havekey = 0;
	int location = 0;
	while(1)
	{
		//这里用来判断里面有没有该key,如果存在则执行获取值,不存在则返回error所指字符串 
		tc = fgetc(database);
		if(tc == EOF)
		{
			break;
		}
		if(tc == '$')
		{
			cancopy = 1;
			continue;
		}
		if(cancopy == 1)
		{
			if(tc == ':')
			{
				location = ftell(database);
				tkey[k] = '\0';
				k = 0;
				cancopy = 0;
				//puts(tkey);
				if(!strcmp(key,tkey))
				{
					havekey = 1;
					//puts("Error:the key exists!");
					break;
				}
				tkey[0] = '\0';
			}
			else
			{
				tkey[k++] = tc;
				continue;
			}
		}
	}
	
	k = 0;
	if(havekey == 1)
	{
		fseek(database,location,SEEK_SET);
		while(1)
		{
			tc = fgetc(database);
			if(tc == '$' || tc == EOF)
			{
				break;
			}
			value = (char*)realloc(value,++k);
			value[k - 1] = tc;
		}
		value[k] = '\0';
		puts("value is:");
		puts(value);
		
		fclose(database);
		return value;
	}
	else
	{
		fclose(database);
		puts("Error:the key doesn't exists,cannot get vlaue!");
		return 0;
	}
}

int setKeyValue(char* key,char* newvalue)
{
	if(rundatabasename[0] == '\0')
	{
		puts("Error:no database is using!");
		return -1;
	}
	if(strlen(key) > 32)
	{
		puts("Warning:the length of key exceeds the limit(32)");
		return 0;
	}
	//puts(rundatabasename);
	for(int i = 0; i < strlen(value);i++)
	{
		if(value[i] == '$')
		{
			puts("Warning:the value can not contain '$'!");
			return 0;
		}
	}
	FILE* database = fopen(rundatabasename,"a+");
	if(database == NULL)
	{
		puts("Error:the database doesn't exist!");
		return -1;
	}
	
	char tkey[33];
	int cancopy = 0;
	int k = 0;
	char tc;
	int havekey = 0;
	int location = 0;
	while(1)
	{
		//这里用来判断里面有没有该key,如果存在则执行设置该key的value,不存在则返回0 
		tc = fgetc(database);
		if(tc == EOF)
		{
			break;
		}
		if(tc == '$')
		{
			cancopy = 1;
			continue;
		}
		if(cancopy == 1)
		{
			if(tc == ':')
			{
				location = ftell(database);
				tkey[k] = '\0';
				k = 0;
				cancopy = 0;
				//puts(tkey);
				if(!strcmp(key,tkey))
				{
					havekey = 1;
					//puts("Error:the key exists!");
					break;
				}
				tkey[0] = '\0';
			}
			else
			{
				tkey[k++] = tc;
				continue;
			}
		}
	}
	
	if(havekey == 1)
	{
		int flag = 0;
		fseek(database,0,SEEK_SET);//将文件指针定位到起始位置
		
		FILE* temp = fopen("settemp.tdb","w");
		if(temp == NULL)
		{
			puts("Error:new settemp-database fail!");
			fclose(database);
			return -1;	
		}
		while(1)
		{
			tc = fgetc(database);
			if(tc == EOF)
			{
				break;
			}
			if(ftell(database) == location)
			{
				fputc(tc,temp);
				flag = 1;
				int len = strlen(newvalue);
				for(int i = 0;i < len;i++)
				{
					fputc(newvalue[i],temp);
				}
				fputc('\n',temp);
			}
			if(flag == 1)
			{
				if((tc == '$' || tc == EOF) && ftell(database) > location)
				{
					flag = 0;
					fputc(tc,temp);

				}
			}
			else
			{
				fputc(tc,temp);
			}
		}
		fclose(database);
		fclose(temp);
		
		remove(rundatabasename);
		rename("settemp.tdb",rundatabasename);
		
		puts("Info:set the key's new value success!");
		return 1;
	}
	else
	{
		fclose(database);
		puts("Error:the key doesn't exists,cannot set set the key's new value!");
		return 0;
	}	
	
}

struct keylistinfo* getKeyList()
{
	if(rundatabasename[0] == '\0')
	{
		puts("Error:no database is using!");
		return NULL;
	}

	//puts(rundatabasename);
	FILE* database = fopen(rundatabasename,"a+");
	if(database == NULL)
	{
		puts("Error:the database doesn't exist!");
		return NULL;
	}
	
	if(keys->n != 0)
	{
		for(int i = 0;i < keys->n;i++)
		{
			free((keys->keylist)[i]);
		}
		keys->keylist = (char**)realloc(keys->keylist,0);
		keys->n = 0;	
	}


	char tkey[33];
	int cancopy = 0;
	int k = 0;
	char tc;
	int location = 0;
	while(1)
	{
		
		tc = fgetc(database);
		if(tc == EOF)
		{
			break;
		}
		if(tc == '$')
		{
			location = ftell(database);
			cancopy = 1;
			continue;
		}
		if(cancopy == 1)
		{
			if(tc == ':')
			{
				tkey[k] = '\0';
				k = 0;
				cancopy = 0;
				//puts(tkey);
				
				keys->keylist = (char**)realloc(keys->keylist,sizeof(char*)*(keys->n + 1));
				(keys->n)++;
				char* thiskey = (char*)malloc(strlen(tkey)*sizeof(char));
				
				strcpy(thiskey,tkey);
				//printf("检查thiskey:%s\n",thiskey);
				(keys->keylist)[keys->n - 1] = thiskey;
				
				
				tkey[0] = '\0';
			}
			else
			{
				tkey[k++] = tc;
				continue;
			}
		}
	}
	
	fclose(database);
	return keys;
}

int getKeySeekIndex()
{
	//暂不实现 
}

3. DustBaseShell模式使用截图

C语言【微项目17】—DustBase微尘数据库[自制键值对数据库][超轻量]【2022-03-23】_第1张图片
C语言【微项目17】—DustBase微尘数据库[自制键值对数据库][超轻量]【2022-03-23】_第2张图片

4. DustBase典型使用流程

  1. int createDataBase(char* databasename);//创建数据库

  2. int usingDataBase(char* databasename);//使用数据库

  3. 使用下列数据库操作函数:
    int putString(char* key,char* value);
    int deleteString(char* key);
    char* getString(char* key,char* error);
    int setKeyValue(char* key,char* newvalue);
    struct keylistinfo* getKeyList();

  4. int clearUsingDataBase();//清除使用的数据库

  5. int deleteDataBase(char* databasename);//删除未使用中的数据库

5. DustBaseCore嵌入式使用

测试文件:importtest.c

#include 
#include "DustBaseCore.c"
int main()
{
	createDataBase("useimport999");
	usingDataBase("useimport999");
	
	putString("godd1","dadasdhjuhfas\ndadasd\tdada8977465=");
	
	putString("peoo","dersaasdasdewqdad");
	
	putString("qdwqd","cfasdsadad");
	
	getString("godd1","error");
	
	struct keylistinfo* keys = getKeyList();
	if(keys != NULL)
	{
		for(int i = 0;i < keys->n;i++)
		{
			if(i == 0)
			{
				printf("[\"%s\"",(keys->keylist)[i]);
			}
			else
			{
				printf(",\"%s\"",(keys->keylist)[i]);
			}
			if(i == keys->n - 1)
			{
				printf("]\n");
			}
		}	
	}
	
	setKeyValue("godd1","this is new value!!!!");
	keys = getKeyList();
	if(keys != NULL)
	{
		for(int i = 0;i < keys->n;i++)
		{
			printf("%s:%s",(keys->keylist)[i],getString((keys->keylist)[i],"error"));
		}	
	}
	
	
	clearUsingDataBase();
	
	
	system("pause");
	return 0;
}

运行截图:
C语言【微项目17】—DustBase微尘数据库[自制键值对数据库][超轻量]【2022-03-23】_第3张图片

6. DustBaseShell模式运行视频

DustBase--微尘数据库,一个十分简单轻量的非关系型——键值对数据库,纯C语言实现!

你可能感兴趣的:(C语言【微项目】,DustBase,微尘数据库,自制键值对数据库,数据库,C语言)