Day39 SQLite数据库操作与文本数据导入
day39 SQLite数据库操作与文本数据导入
本节内容围绕使用 C 语言结合 SQLite3 库,将一个纯文本词典文件 dict.txt
中的数据导入到 SQLite 数据库中。涵盖了数据库连接、表的创建与删除、SQL 命令执行、文件读取、字符串处理等核心知识点。代码完整,逻辑清晰,适合嵌入式或系统级开发中轻量级数据存储场景的学习与应用。
🧩 知识点概览
- 使用
sqlite3_open()
打开或创建数据库 - 使用
sqlite3_exec()
执行 SQL 语句(建表、删表、插入) - 错误处理机制:
sqlite3_errstr()
和errmsg
- 文件操作:
fopen()
、fgets()
逐行读取 - 字符串分割:
strtok()
提取单词与释义 - 动态生成 SQL 插入语句:
sprintf()
- 内存管理与资源释放:
sqlite3_free()
、fclose()
、sqlite3_close()
✅ 完整代码(含详细注释)
#include <sqlite3.h> // 引入SQLite数据库操作库
#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库(包含内存管理等函数)
#include <string.h> // 引入字符串处理库int main(int argc, char** argv)
{sqlite3* db = NULL; // 声明SQLite数据库连接句柄char* errmsg = NULL; // 声明用于存储SQL操作错误信息的指针// 打开或创建名为aaa.db的数据库文件int ret = sqlite3_open("./aaa.db", &db);// 检查数据库打开是否成功if (SQLITE_OK != ret){// 输出打开数据库失败的错误信息fprintf(stderr, " sqlite3_open %s\n", sqlite3_errstr(ret));sqlite3_close(db); // 关闭数据库连接return 1; // 程序异常退出}char sql_cmd[1024] = {0}; // 声明用于存储SQL命令的字符数组并初始化// 删除已存在的dict表(若存在)strcpy(sql_cmd, "drop table dict");sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);// 注意:即使表不存在,drop也会报错,但可忽略;此处未检查返回值,属于容错性设计// 清空sql_cmd数组,准备创建新表的SQL命令bzero(sql_cmd, sizeof(sql_cmd));// 复制创建dict表的SQL命令到sql_cmd,表包含id(整数)、word(字符)、dict_mean(文本)字段strcpy(sql_cmd, "create table dict(id int ,word char ,dict_mean text);");// 执行创建表的SQL命令ret = sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);// 检查表是否创建成功if (SQLITE_OK != ret){// 输出创建表失败的错误信息,包含执行的SQL命令和具体错误fprintf(stderr, " sqlite3_exec sql_cmd:[%s] %s\n", sql_cmd, errmsg);sqlite3_free(errmsg); // 释放错误信息占用的内存sqlite3_close(db); // 关闭数据库连接return 1; // 程序异常退出}// 打开指定路径下的dict.txt文件,用于读取数据FILE* fp = fopen("./dict.txt", "r");// 检查文件是否打开成功if (NULL == fp){perror("fopen"); // 输出文件打开失败的错误信息return 1; // 程序异常退出}int num = 1; // 声明并初始化记录序号的变量,从1开始// 循环读取文件内容,直到文件结束while (1){char linebuf[1024] = {0}; // 声明用于存储读取到的一行数据的字符数组并初始化// 从文件中读取一行数据到linebuf,若读取失败(如文件结束)则跳出循环if (NULL == fgets(linebuf, sizeof(linebuf), fp)){break;}// 使用空格分割一行数据,获取单词部分(word)char *word = strtok(linebuf, " ");// 继续分割剩余部分,以回车符为分隔符,获取释义部分(mean)char *mean = strtok(NULL, "\r");// 清空sql_cmd数组,准备生成插入数据的SQL命令bzero(sql_cmd, sizeof(sql_cmd));// 生成插入数据的SQL命令,将序号、单词、释义插入到dict表sprintf(sql_cmd, "insert into dict values(%d,\"%s\",\"%s\");", num++, word, mean);// 执行插入数据的SQL命令ret = sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);// 检查数据是否插入成功if (SQLITE_OK != ret){// 输出插入数据失败的错误信息,包含执行的SQL命令和具体错误fprintf(stderr, " sqlite3_exec sql_cmd:[%s] %s\n", sql_cmd, errmsg);sqlite3_free(errmsg); // 释放错误信息占用的内存sqlite3_close(db); // 关闭数据库连接fclose(fp); // 关闭文件指针return 1; // 程序异常退出}}fclose(fp); // 关闭文件sqlite3_close(db); // 关闭数据库连接return 0; // 程序正常退出
}
📌 代码说明与关键点解析
步骤 | 说明 |
---|---|
1. 数据库连接 | 使用 sqlite3_open("./aaa.db", &db) 打开本地数据库文件,若不存在则自动创建。 |
2. 表结构清理与重建 | 先 drop table dict 删除旧表,再 create table dict(...) 创建新表,确保环境干净。 |
3. 文件读取 | 使用 fopen() 打开 /home/linux/dict.txt ,逐行读取词条。每行格式应为:单词 释义 (中间用空格分隔)。 |
4. 字符串解析 | 使用 strtok() 第一次按空格切分出 word ,第二次按 \r 切分出 mean (兼容 Windows 换行)。 |
5. SQL 插入语句构造 | 使用 sprintf() 将 id 、word 、mean 格式化为 INSERT INTO 语句。 |
6. 错误处理 | 所有 sqlite3_exec() 调用后均判断返回值,出错时打印 SQL 语句及错误信息,并释放资源退出。 |
7. 资源释放 | 正确关闭文件和数据库连接,避免资源泄漏。 |
⚠️ 注意:
strtok(NULL, "\r")
可能无法正确处理\n
或\r\n
换行,建议增强为"\r\n"
。- 若
dict.txt
中有特殊字符(如引号),可能导致 SQL 语法错误,建议使用参数化查询(但本例未使用)。
🧪 示例输入文件:dict.txt
假设 dict.txt
内容如下:
apple a fruit that grows on trees
book something you read
cat a small domesticated animal
hello greeting used when meeting someone
world the planet Earth
🧱 生成的数据库表结构
字段名 | 类型 | 说明 |
---|---|---|
id | int | 自增序号 |
word | char | 单词 |
dict_mean | text | 释义 |
✅ 理想运行结果
-
成功编译并运行程序:
gcc -o dict_import dict_import.c -lsqlite3 ./dict_import
-
生成数据库文件
aaa.db
。 -
可通过 SQLite 命令行验证数据:
sqlite3 aaa.db
在 SQLite 提示符下执行:
select count(id) from dict;
理想输出:
5
表示成功插入 5 条记录。
-
查看所有数据:
SELECT * FROM dict LIMIT 5;
理想输出示例:
1|apple|a fruit that grows on trees 2|book|something you read 3|cat|a small domesticated animal 4|hello|greeting used when meeting someone 5|world|the planet Earth
🔚 总结
本日任务实现了 从文本文件到 SQLite 数据库的完整数据迁移流程,涉及 C 语言与数据库交互的核心技能:
- 数据库的打开与关闭
- 表的创建与删除
- 动态 SQL 语句拼接
- 文本文件解析
- 错误处理与资源管理
该程序可用于构建小型离线词典、配置管理、日志存储等场景,是嵌入式开发中非常实用的技术组合。