Day39 SQLite数据库操作与文本数据导入

发布于:2025-09-10 ⋅ 阅读:(22) ⋅ 点赞:(0)

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()idwordmean 格式化为 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 释义

✅ 理想运行结果

  1. 成功编译并运行程序:

    gcc -o dict_import dict_import.c -lsqlite3
    ./dict_import
    
  2. 生成数据库文件 aaa.db

  3. 可通过 SQLite 命令行验证数据:

    sqlite3 aaa.db
    

    在 SQLite 提示符下执行:

    select count(id) from dict;
    

    理想输出:

    5
    

    表示成功插入 5 条记录。

  4. 查看所有数据:

    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 语句拼接
  • 文本文件解析
  • 错误处理与资源管理

该程序可用于构建小型离线词典、配置管理、日志存储等场景,是嵌入式开发中非常实用的技术组合。


网站公告

今日签到

点亮在社区的每一天
去签到