C语言 开发篇+一个简单的数据库管理系统ZDB

说明:本文供数据库爱好者和初级开发人员学习使用
标签:数据库管理系统、RDBMS、C语言小程序、C语言、C程序
系统:Windows 11 x86
CPU :Intel
IDE :CLion
语言:C语言
标准:C23
提示:如果您发现本文哪里写的有问题或者有更好的写法请留言或私信我进行修改优化


★ 程序界面

★ 功能简介

目前该C语言小程序实现了RDBMS上表的几个基础功能,如:
✔ DDL:create、drop、alter、truncate、flashback、purge
✔ DML:insert、delete、update、select

★ 程序特点

✔ 程序会在首次运行时在同级创建一个目录用于存放数据库信息
✔ 程序运行期间表数据存储在内存中,类似于Redis
✔ 程序运行结束表数据会刷入磁盘避免丢失
✔ 表在删除后清理前支持闪回功能,清理后空间可以复用
✔ 表记录在删除后只是标记为删除,方便后期复用并减少数据shrink的性能消化

★ 程序试用

https://download.csdn.net/download/zzt_2009/88792573

★ 使用案例

##########【欢迎使用 ZDB】##########
# 作者:zzt_2009     版本:V 5.0.0 #
# [H/h]查看帮助      [E/e]退出程序 #
首次使用,正在初始化数据字典……
字典落盘成功!
字典文件初始化完成。
首次使用,正在初始化数据文件……
数据落盘成功!
数据文件初始化完成。
首次使用,已为您展示帮助文档。
# L   For > list table def   #
# C   For > Create table     #
# D   For > Drop table       #
# A   For > Alter table      #
# R   For > Rename table     #
# T   For > Truncate table   #
# F   For > Flashback table  #
# P   For > Purge recyclebin #
# i   For > insert           #
# d   For > delete           #
# u   For > update           #
# s   For > select           #
# c   For > clear            #
# H/h For > help             #
# E/e For > exit             #
SQL > H
# L   For > list table def   #
# C   For > Create table     #
# D   For > Drop table       #
# A   For > Alter table      #
# R   For > Rename table     #
# T   For > Truncate table   #
# F   For > Flashback table  #
# P   For > Purge recyclebin #
# i   For > insert           #
# d   For > delete           #
# u   For > update           #
# s   For > select           #
# c   For > clear            #
# H/h For > help             #
# E/e For > exit             #
SQL > L
# 库中所有状态的表信息如下
内存ID  表名 表状态 表编号 行数    列数
TMID[0]   T0 STA[2] OID[0] ROWS[4] COLS[2]
# STA列值:1>新/空表、2>有数据、3>已删除、4>可复用  
SQL > C
请输入表名: T1
请输入列的[数量]:2
列的[数量]:2
请输入第[1]列的[名称]:ID
请输入第[2]列的[名称]:NAME
表TMID:1,表OID:2字典落盘成功!
数据落盘成功!
SQL > C
请输入表名: T2
请输入列的[数量]:2
列的[数量]:2
请输入第[1]列的[名称]:ID
请输入第[2]列的[名称]:NAME
表TMID:2,表OID:3字典落盘成功!
数据落盘成功!
SQL > D
请输入表名: T1
已删除
字典落盘成功!
数据落盘成功!
SQL > F
请输入表OID: 1
表已闪回
字典落盘成功!
数据落盘成功!
SQL > R
请输入表名: 1
请输入新名: T1
# 更新成功:
# 库中所有状态的表信息如下
内存ID  表名 表状态 表编号 行数    列数
TMID[0]   T0 STA[2] OID[0] ROWS[4] COLS[2]
TMID[1]   T1 STA[1] OID[1] ROWS[0] COLS[2]
TMID[2]   T2 STA[1] OID[2] ROWS[0] COLS[2]
# STA列值:1>新/空表、2>有数据、3>已删除、4>可复用  
字典落盘成功!
数据落盘成功!
SQL > A
请输入表名: T1
请输入CID(列号): 1
请输入字段新值: ID2
# 更新后表结构和数据如下:
R[00] RMID[00] : ID2    NAME
# [0]ROWS,[2]COLS
字典落盘成功!
数据落盘成功!
SQL > i
请输入表名: T1
请输入多行(列以tab分隔,新行";\n"结束)
Input > 1       a
Input > 2       b
Input > 3       c
Input > ;
插入结束!
字典落盘成功!
数据落盘成功!
# 表[T1]最新数据如下:
R[00] RMID[00] : ID2    NAME
R[01] RMID[01] : 1      a
R[02] RMID[02] : 2      b
R[03] RMID[03] : 3      c
# [3]ROWS,[2]COLS
表行列数不正确,修正完成.
数据落盘成功!
SQL > d
请输入表名: T1
请输入RMID: 2
# RID[2]已删除
# 删除后表数据如下:
R[00] RMID[00] : ID2    NAME
R[01] RMID[01] : 1      a
R[02] RMID[03] : 3      c
# [2]ROWS,[2]COLS
表行列数不正确,修正完成.
数据落盘成功!
字典落盘成功!
数据落盘成功!
SQL > u
请输入表名: T1
请输入RMID(内存行号): 3
请输入CID(列号): 2
请输入字段新值: ccc
# 更新后表数据如下:
R[00] RMID[00] : ID2    NAME
R[01] RMID[01] : 1      a
R[02] RMID[03] : 3      ccc
# [2]ROWS,[2]COLS
字典落盘成功!
数据落盘成功!
SQL > e
字典落盘成功!
数据落盘成功!
#######【感谢使用 ZDB 再见!】#######进程已结束,退出代码0

★ 程序源码

//引用头文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <direct.h>//使用宏定义代替相关内容
#define R 99  //行
#define C 99  //列
#define N 32  //名称
#define L 99  //长度
#define S 32  //SIZE
#define DefaultPATH ".\\ZDATA\\"//全局变量
int i, j, k = 0; //
int fr, fc = 0; //文件行数,文件列数
int rn, cn = 0; //行号、列号
int oid, noid = 0; //全局对象号、内存号
char g_temp[L]; //临时使用的字符串变量
char table_name[N]; //表名
FILE *fp;
char Path[L];
char dict_file[N] = "ZDB.dic"; //文件名
char data_file[N] = "ZDB.dat"; //文件名
typedef struct {     //字典int state;       //状态:0>未分配、1>有效、2>删除char name[N];    //名称char value[L];   //值char comment[L]; //描述
} S_Dict;
S_Dict g_dict[S];
typedef struct {     //表int state;       //状态:0>未分配、1>新表、2>有数、3>删除、4>可复用char name[N];    //名称int oid;         //编号int rows;        //行数int cols;        //列数char record[R][C][L]; //数据&状态:"">未分配、H>字段名、A>可用、D>删除
} S_Table;
S_Table g_table[S];//函数声明
int Head(); //界面输出
int Body(); //程序主体
int Bye(); //程序退出
int Help(); //
int Iint_DB(); //
int Iint_Dir(); //
int Data_Read(); //
int Data_Write(); //
int Dict_Read(); //
int Dict_Write(); //
int List_Table(); //
int Create(char table_name[N]); //
int Drop(char table_name[N]); //
int Alter(char table_name[N], int cn, char g_temp[L]); //
int Truncate(char table_name[N]); //
int Purge(); //
int Flashback(int oid); //
int Rename(char table_name[N], char g_temp[L]); //
int Insert(char table_name[N]); //
int Delete(char table_name[N], int rn); //
int Update(char table_name[N], int rn, int cn, char g_temp[L]); //
int Select(char table_name[N]); ////主函数
int main() {Head();Dict_Read();Data_Read();Body();return 0;
}//函数定义
int Head() {system("CLS");printf("##########【欢迎使用 ZDB】##########\n");printf("# 作者:zzt_2009     版本:V 5.0.0 #\n");printf("# [H/h]查看帮助      [E/e]退出程序 #\n");return 1;
}int Body() {//命令判断while (1) {printf("SQL > ");int n;n = getch();printf("%c\n", (char) n); //输出按键switch (n) {case 76: // L -> list table definationList_Table();break;case 67: // C -> createprintf("请输入表名: ");scanf("%s", table_name);Create(table_name);break;case 68: // D -> dropprintf("请输入表名: ");scanf("%s", table_name);Drop(table_name);break;case 65: // A -> alterprintf("请输入表名: ");scanf("%s", table_name);printf("请输入CID(列号): ");scanf("%d", &cn);printf("请输入字段新值: ");scanf("%s", g_temp);Alter(table_name, cn, g_temp);break;case 70: // F -> flashbackprintf("请输入表OID: ");scanf("%d", &oid);Flashback(oid);break;case 80: // P -> purgePurge();break;case 84: // T -> truncateprintf("请输入表名: ");scanf("%s", table_name);Truncate(table_name);break;case 82: // R -> renameprintf("请输入表名: ");scanf("%s", table_name);printf("请输入新名: ");scanf("%s", g_temp);Rename(table_name, g_temp);break;case 105: // i -> insertprintf("请输入表名: ");scanf("%s", table_name);Insert(table_name);break;case 100: // d -> deleteprintf("请输入表名: ");scanf("%s", table_name);printf("请输入RMID(内存行号): ");scanf("%d", &rn);Delete(table_name, rn);break;case 117: // u -> updateprintf("请输入表名: ");scanf("%s", table_name);printf("请输入RMID(内存行号): ");scanf("%d", &rn);printf("请输入CID(列号): ");scanf("%d", &cn);printf("请输入字段新值: ");scanf("%s", g_temp);Update(table_name, rn, cn, g_temp);break;case 115: // s -> selectprintf("请输入表名: ");scanf("%s", table_name);Select(table_name);break;case 99: // c -> clearHead();break;case 72:  // H -> helpcase 104: // h -> helpHelp();break;case 69:  // E -> exitcase 101: // e -> exitDict_Write();Data_Write();Bye();exit(0);default:printf("命令不正确请重新输入,或按[H/h]查看帮助\n");break;}}
}int Bye() {printf("#######【感谢使用 ZDB 再见!】#######\n");return 0;
}int Help() {printf("# L   For > list table def   #\n");printf("# C   For > Create table     #\n");printf("# D   For > Drop table       #\n");printf("# A   For > Alter table      #\n");printf("# R   For > Rename table     #\n");printf("# T   For > Truncate table   #\n");printf("# F   For > Flashback table  #\n");printf("# P   For > Purge recyclebin #\n");printf("# i   For > insert           #\n");printf("# d   For > delete           #\n");printf("# u   For > update           #\n");printf("# s   For > select           #\n");printf("# c   For > clear            #\n");printf("# H/h For > help             #\n");printf("# E/e For > exit             #\n");
}int Dict_Read() {//printf("字典加载中…………\n");strcpy(Path, DefaultPATH);strcat(Path, dict_file);fp = fopen(Path, "rb");if (fp == NULL) {printf("首次使用,正在初始化数据字典……\n");Iint_DB();Iint_Dir();Dict_Write();printf("字典文件初始化完成。\n");}fread(&g_dict, sizeof(S_Dict), S, fp);fclose(fp);noid = atoi(g_dict[0].value);//printf("字典文件已加载[noid:%d]\n", noid);return 0;
}int Data_Read() {//printf("数据加载中…………\n");strcpy(Path, DefaultPATH);strcat(Path, data_file);fp = fopen(Path, "rb");if (fp == NULL) {printf("首次使用,正在初始化数据文件……\n");Iint_DB();Iint_Dir();Data_Write();printf("数据文件初始化完成。\n");//printf("首次使用,已为您展示帮助文档。\n");Help();}fread(&g_table, sizeof(S_Table), S, fp);fclose(fp);//printf("数据文件已加载[%s]\n", g_table[0].name);return 0;
}int Iint_DB() {//数据字典g_dict[0].state = 1;strcpy(g_dict[0].name, "noid");strcpy(g_dict[0].value, "1");strcpy(g_dict[0].comment, "下一个对象的编号");//案例表strcpy(g_table[0].name, "T0");g_table[0].state = 2;g_table[0].oid = 0;g_table[0].rows = 4;g_table[0].cols = 2;g_table[0].oid = 0;strcpy(g_table[0].record[0][0], "H");strcpy(g_table[0].record[0][1], "TEL");strcpy(g_table[0].record[0][2], "NAME");strcpy(g_table[0].record[1][0], "A");strcpy(g_table[0].record[1][1], "110");strcpy(g_table[0].record[1][2], "Police");strcpy(g_table[0].record[2][0], "A");strcpy(g_table[0].record[2][1], "120");strcpy(g_table[0].record[2][2], "Ambulance");strcpy(g_table[0].record[3][0], "A");strcpy(g_table[0].record[3][1], "119");strcpy(g_table[0].record[3][2], "Fire");return 0;
}int Iint_Dir() {if (_mkdir(DefaultPATH) == 0) {//printf("目录创建成功!\n");} else {//printf("目录已存在!\n");}return 0;
}int Dict_Write() {strcpy(Path, DefaultPATH);strcat(Path, dict_file);fp = fopen(Path, "wb");if (fp == NULL) {printf("无法打开文件\n");exit(1);}fwrite(&g_dict, sizeof(S_Dict), S, fp);fclose(fp);printf("字典落盘成功!\n");return 0;
}int Data_Write() {strcpy(Path, DefaultPATH);strcat(Path, data_file);fp = fopen(Path, "wb");if (fp == NULL) {printf("无法打开文件\n");exit(1);}fwrite(&g_table, sizeof(S_Table), S, fp);fclose(fp);printf("数据落盘成功!\n");return 0;
}int List_Table() {i = 0;printf("# 库中所有状态的表信息如下\n");printf("内存ID  表名 表状态 表编号 行数    列数\n");while (g_table[i].state != 0) {printf("TMID[%d] %4s STA[%d] OID[%d] ROWS[%d] COLS[%d]\n",i, g_table[i].name, g_table[i].state, g_table[i].oid, g_table[i].rows, g_table[i].cols);i++;}printf("# STA列值:1>新/空表、2>有数据、3>已删除、4>可复用\n");
}int Create(char table_name[N]) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 1) || (g_table[i].state == 2))) {printf("表已存在\n");goto label_Create_end;}i++;}//寻找可写的区域+重置之前的表记录状态为Di = 0;while (i < S) {if ((g_table[i].state == 0) || (g_table[i].state == 4)) {g_table[i].state = 1; //设置表状态为:0>未分配、1>空表、2>有数、3>删除、4>清除g_table[i].oid = noid;g_table[i].rows = 0;g_table[i].cols = 0;strcpy(g_table[i].name, table_name);//记录列定义strcpy(g_table[i].record[0][0], "H"); //record状态:H>字段名、A>可用、D>删除printf("请输入列的[数量]:");scanf("%d", &g_table[i].cols);printf("列的[数量]:%d\n", g_table[i].cols);for (j = 0; j < g_table[i].cols; j++) {printf("请输入第[%d]列的[名称]:", j + 1);scanf("%s", &g_table[i].record[0][j + 1]);}noid++;strcpy(g_dict[0].value, itoa(noid, g_temp, L));//调试printf("表TMID:%d,表OID:%d", i, noid);//重置表旧数据状态j = 1;while (strlen(g_table[i].record[j][0]) != 0) {strcpy(g_table[i].record[j][0], "");j++;}//写盘Dict_Write();Data_Write();return 1;}i++;}printf("表空间已满,请扩容!");//goto标签label_Create_end:return 0;
}int Drop(char table_name[N]) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 1) || (g_table[i].state == 2))) {//标记表状态为删除状态g_table[i].state = 3;printf("已删除\n");//写盘Dict_Write();Data_Write();return 1;}i++;}printf("表不存在!\n");
}int Alter(char table_name[N], int cn, char g_temp[L]) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 1) || (g_table[i].state == 2))) {//表存在则更新字段rn = 0;if (cn != 0) {strcpy(g_table[i].record[rn][cn], g_temp);printf("# 更新后表结构和数据如下:\n");Select(table_name);//写盘Dict_Write();Data_Write();return 1;}printf("非列名位置不容许DDL!\n");return 1;}i++;}printf("表不存在!\n");
}int Rename(char table_name[N], char g_temp[L]) {//判断新名是否冲突i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, g_temp) == 0) && ((g_table[i].state == 1) || (g_table[i].state == 2))) {printf("新表名已存在!\n");return 0;}i++;}//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 1) || (g_table[i].state == 2))) {//更新strcpy(g_table[i].name, g_temp);printf("# 更新成功:\n");List_Table();//写盘Dict_Write();Data_Write();return 1;}i++;}printf("表不存在!\n");
}int Truncate(char table_name[N]) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 1) || (g_table[i].state == 2))) {//标记状态g_table[i].state = 1;//重置表旧数据状态j = 1;while (strlen(g_table[i].record[j][0]) != 0) {strcpy(g_table[i].record[j][0], "");j++;}printf("表已清空\n");//写盘Dict_Write();Data_Write();return 1;}i++;}printf("表不存在!\n");
}int Purge() {//标记所有删除状态的表为可复用状态i = 0;while (g_table[i].state != 0) {if (g_table[i].state == 3) {//标记状态g_table[i].state = 4;}i++;}printf("回收站已清空!\n");//写盘Dict_Write();Data_Write();return 1;
}int Flashback(int oid) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((g_table[i].oid == oid) && (g_table[i].state == 3)) {//标记状态if (strlen(g_table[i].record[1][0]) == 0) {g_table[i].state = 1;} else {g_table[i].state = 2;}strcpy(g_table[i].name, itoa(g_table[i].oid, g_temp, L));printf("表已闪回\n");//写盘Dict_Write();Data_Write();return 1;}i++;}printf("表不存在或已被清理!\n");
}int Insert(char table_name[N]) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 1) || (g_table[i].state == 2))) {//插入数据char *token;j = 0; //j记录输入了多少行printf("请输入多行(列以tab分隔,新行\";\\n\"结束)\n");//循环读取每行输入直到达到最大行数或者遇到文件结束符EOFwhile (j < R && fgets(g_temp, sizeof(g_temp), stdin)) {if (strcmp(g_temp, ";\n") == 0) { // 如果输入为";\n",则结束输入break;}//打印输入提示符printf("Input > ");// 使用strtok分割输入字符串并存入表字段中token = strtok(g_temp, "\t\n");rn = 1; //由于第一行存储了表列信息,因此从第二行开始cn = 1; //将输入按token存入1开头的数组中while (rn < R) { //遍历表record,找到可以存储的位置if ((strcmp(g_table[i].record[rn][0], "D") == 0) || (strlen(g_table[i].record[rn][0]) == 0)) {while (token != NULL && cn < C) {strcpy(g_table[i].record[rn][0], "A"); //设置record插入的首列strncpy(g_table[i].record[rn][cn], token, L);g_table[i].record[rn][cn][L - 1] = '\0'; // 确保字符串以null字符结尾token = strtok(NULL, "\t\n");cn++;}break;}rn++;}j++;}printf("插入结束!\n");//修改表状态g_table[i].state = 2;//写盘Dict_Write();Data_Write();//查看插入结果printf("# 表[%s]最新数据如下:\n", g_table[i].name);Select(g_table[i].name);return 1;}i++;}printf("表不存在!\n");return 0;
}int Delete(char table_name[N], int rn) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 2) || (g_table[i].state == 1))) {//空表提示if (g_table[i].state == 1) {printf("# 空表,无法DML!\n");return 0;}//标记行if (rn != 0) {strcpy(g_table[i].record[rn][0], "D");printf("# RMID[%d]已删除\n", rn);printf("# 删除后表数据如下:\n");Select(table_name);//写盘Dict_Write();Data_Write();return 1;}printf("首行为列名不容许删除!\n");return 1;}i++;}printf("表不存在!\n");
}int Update(char table_name[N], int rn, int cn, char g_temp[L]) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 2) || (g_table[i].state == 1))) {//空表提示if (g_table[i].state == 1) {printf("# 空表,无法DML!\n");return 0;}//更新字段if ((rn != 0) && (cn != 0) && (strcmp(g_table[i].record[rn][0], "A") == 0)) {//printf("%d %d %s %d\n", rn, cn, g_table[i].record[rn][0], strcmp(g_table[i].record[rn][0], "A"));strcpy(g_table[i].record[rn][cn], g_temp);printf("# 更新后表数据如下:\n");Select(table_name);//写盘Dict_Write();Data_Write();return 1;}printf("不容许DML的位置!\n");return 1;}i++;}printf("表不存在!\n");
}int Select(char table_name[N]) {//判断表是否存在i = 0;while (g_table[i].state != 0) {if ((strcmp(g_table[i].name, table_name) == 0) && ((g_table[i].state == 2) || (g_table[i].state == 1))) {//输出内容j = 0;k = 0;rn = 0;while (strlen(g_table[i].record[rn][0]) != 0) { //遍历非空数组if (strcmp(g_table[i].record[rn][0], "D") != 0) { //检索非delete状态的记录cn = 0;printf("R[%02d] RMID[%02d] : ", k, rn);while (strlen(g_table[i].record[rn][cn]) != 0) {printf("%s\t", g_table[i].record[rn][cn + 1]);j++;cn++;}printf("\n");k++;}rn++;}rn = k - 1;cn = j / (rn + 1) - 1;printf("# [%d]ROWS,[%d]COLS\n", rn, cn);//修正字典if ((g_table[i].rows != rn) || (g_table[i].cols != cn)) {g_table[i].rows = rn;g_table[i].cols = cn;printf("表行列数不正确,修正完成.\n", rn, cn);Data_Write();}return 1;}i++;}printf("表不存在!\n");
}//end

※ 如果您觉得文章写的还不错, 别忘了在文末给作者点个赞哦 ~

20200426194203245.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/442386.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Phoncent博客,探索Rie Kudan的GPT创作之举

近日&#xff0c;大家都在谈论日本作家Rie Kudan&#xff0c;她凭借其小说《东京共鸣塔》&#xff08;"Tokyo-to Dojo-to"&#xff09;荣获了日本极具声望的芥川奖。这本小说引起了广泛的讨论和思考&#xff0c;因为令人惊讶的是&#xff0c;Kudan在其中直接引用了人…

怎样选择多线程多进程和多协程?

有这么多可以实现并发的方式方法,那么,我们怎么确定在合适的时机采用合适的实现方法呢?这就需要我们对各个实现并发的方式方法有一个全面的概念性的理解,以及他们的内在执行逻辑优缺点有一个清晰的认识! 如下图所示,首先我们需要对单进程、多进程、多线程及多协程之间有…

JavaScript中的闭包

闭包&#xff1a;闭包是一个组合&#xff0c;一个函数以及它捆绑的周边环境状态的引用组成的组合 闭包 函数 这个函数捆绑的周边环境状态的引用 闭包的表现形式 1、函数作为参数 <!DOCTYPE html> <html> <head> <meta charset"utf-…

Wireshark网络协议分析 - TCP协议

在我的博客阅读本文 文章目录 1. 基础2. 实战2.1. 用Go写一个简单的TCP服务器与客户端2.2. Wireshark抓包分析2.3. 限制数据包的大小——MSS与MTU2.4. 保证TCP的有序传输——Seq&#xff0c;Len与Ack2.5. TCP头标志位——URG&#xff0c;ACK&#xff0c;PSH&#xff0c;RST&…

MyBatis常见面试题汇总

说一下MyBatis执行流程&#xff1f; MyBatis是一款优秀的基于Java的持久层框架&#xff0c;它内部封装了JDBC&#xff0c;使开发者只需要关注SQL语句本身&#xff0c;而不需要花费精力去处理加载驱动、创建连接等的过程&#xff0c;MyBatis的执行流程如下&#xff1a; 加载配…

TCP/IP网络模型

大家好我是苏麟 , 今天聊聊TCP/IP四层网络模型 . 资料来源 : 小林coding 小林官方网站 : 小林coding (xiaolincoding.com) 应用层 最上层的&#xff0c;也是我们能直接接触到的就是应用层&#xff08;Application Layer&#xff09;&#xff0c;我们电脑或手机使用的应用软件都…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Gauge组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Gauge组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Gauge组件 数据量规图表组件&#xff0c;用于将数据展示为环形图表。 子组件 无…

如何用Docker+jenkins 运行 python 自动化?

1.在 Linux 服务器安装 docker 2.创建 jenkins 容器 3.根据自动化项目依赖包构建 python 镜像(构建自动化 python 环境) 4.运行新的 python 容器&#xff0c;执行 jenkins 从仓库中拉下来的自动化项目 5.执行完成之后删除容器 前言 环境准备 Linux 服务器一台(我的是 CentOS7)…

harmony开发ohpm mac环境配置

Mac电脑 安装 Ohpm &#xff5c;HarmonyOS 安装 Ohpm ohpm环境配置好后&#xff0c;执行ohpm会报如下的错 ohpm has not been initialized yet. Execute the init script to initialize it first. 解决办法 鸿蒙OS开发&#xff0c;解决报错“ohpm has not been initialized yet…

架构秘笈:移花接木。使用mysql模拟redis

这年头&#xff0c;你看到的东西未必就是你认为的东西。一个 mysql 协议的后面&#xff0c;可能是tidb&#xff1b;一个 linux 机器后面&#xff0c;可能是一个精简的 docker &#xff1b;你觉得xjjdog是个女的&#xff0c;但可能ta自己也不太清楚&#xff1b;而当你大呼 php万…

活动回顾 | 矩阵起源 CEO 王龙:与大数据结合,是大模型成熟的必经之路

导读 近日&#xff0c;由数据猿和上海大数据联盟主办&#xff0c;上海市经济和信息化委员会、上海市科学技术委员会指导的“第六届金猿季&魔方论坛——大数据产业发展论坛”在上海市四行仓库举行&#xff0c;吸引了数百位业界精英的参与。 本次论坛以“小趋势大未来”为主…

揭开空白网页背景色的神秘面纱

前言 一个看似简单实则有坑的问题&#xff1a;空白网页的背景色是什么&#xff1f; 大家是不是都会认为是白色&#xff0c;但事实并非如此&#xff0c;有时候我们眼睛看到的也不一定是真的&#x1f9d0; 页面根元素背景色 比如下面这段代码&#xff1a; <!-- ... --> <…