SQLite 中文写入失败问题总结

SQLite 中文写入失败问题总结与解决方案

在 Windows 下使用 C++ 操作 SQLite 数据库时,中文字段经常出现 写入成功但内容显示为 BLOB 或 乱码 的问题。根本原因在于 SQLite 要求字符串以 UTF-8 编码 存储,而默认的 std::string 中文通常是 GB2312/ANSI 编码。

🧩 问题现象

在 C++ (如 Visual Studio) 中使用 std::string 把含有中文的字符串插入到 SQLite 数据库时:

  • 插入后数据表中文本列显示为 BLOB
  • 或者表面显示为 乱码,无法正常显示中文

示例

cpp 复制代码
std::string desc = "搬运动作:从 Port2 取片 → Port3 放片";
m_pDB->executeQuery("INSERT INTO ... VALUES ('" + desc + "');");

结果: description 列在 SQLite 中显示为 BLOB,而不是文本


🔍 根本原因

SQLite 要求所有 TEXT 类型的字符串必须为 UTF-8 编码。

而 VS 编译器中直接写入 std::string 的中文,实际编码是 GB2312 / GBK / ANSI,并非 UTF-8

导致结果:

  • SQLite 无法识别非 UTF-8 内容,转而存储成 BLOB

✅ 解决方案

✅ 方法一:使用 ansiToUtf8() 将 ANSI 转换为 UTF-8

cpp 复制代码
// 本地编码转为 UTF-8
std::string TransferManager::ansiToUtf8(const std::string& ansiStr) {
    int wideLen = MultiByteToWideChar(CP_ACP, 0, ansiStr.c_str(), -1, nullptr, 0);
    std::wstring wideStr(wideLen, 0);
    MultiByteToWideChar(CP_ACP, 0, ansiStr.c_str(), -1, &wideStr[0], wideLen);

    int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, nullptr, 0, nullptr, nullptr);
    std::string utf8Str(utf8Len, 0);
    WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, &utf8Str[0], utf8Len, nullptr, nullptr);

    utf8Str.pop_back(); // 去掉最后的 '\0'
    return utf8Str;
}

使用:

cpp 复制代码
std::string raw = "搬运动作:从 Port2 取片 → Port3 放片"; // 系统本地编码
std::string utf8 = TransferManager::ansiToUtf8(raw);
data.strDescription = utf8;

✅ 方法二:如果使用了 Unicode 工程(如 std::wstring / CStringW)

可使用:

cpp 复制代码
std::string TransferManager::wstringToUtf8(const std::wstring& wstr);

或者使用 CStringW → std::wstring → UTF-8

cpp 复制代码
CStringW wdesc = L"搬运动作:从 Port2 取片 → Port3 放片";
data.strDescription = TransferManager::wstringToUtf8(std::wstring(wdesc));

📦 可选补充:从 SQLite 中读取 UTF-8 → 转为本地编码显示

cpp 复制代码
// UTF-8 转为本地编码
std::string TransferManager::utf8ToAnsi(const std::string& utf8Str) {
    int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0);
    std::wstring wideStr(wideLen, 0);
    MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wideStr[0], wideLen);

    int ansiLen = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, NULL, 0, NULL, NULL);
    std::string ansiStr(ansiLen, 0);
    WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, &ansiStr[0], ansiLen, NULL, NULL);

    ansiStr.pop_back(); // 去掉最后的 '\0'
    return ansiStr;
}

可用于日志输出或 UI 控件显示。


🧪 实际检测建议

插入前输出:

cpp 复制代码
printf("准备插入 UTF-8 字符串:%s\n", data.strDescription.c_str());

验证方式:

  • SQLite 中字段类型应为 TEXT,不是 BLOB
  • DB Browser 应正常显示中文,不是问号或乱码

🧠 最佳实践

场景 建议方式
插入中文到 SQLite ansiToUtf8
从 SQLite 读取后展示 utf8ToAnsi
项目编码设置 设置为 UTF-8 无 BOM
VS 源文件保存编码 另存为 UTF-8 编码

✅ 总结

只要 std::string 中的中文不是 UTF-8 编码,SQLite 插入后就会出现异常(显示为 BLOB 或乱码)。

相关推荐
姜鱼问生1 天前
Kuma SQLite 备份坑
数据库·sqlite
橙光成长2 天前
Context Mode 深度解析:用沙盒、SQLite 与钩子路由,把 AI 编码 Agent 的上下文消耗削减 98%
数据库·人工智能·sqlite
阿星_2 天前
Linux Ubuntu 查看 SQLite 工具
linux·ubuntu·sqlite
jiushidt3 天前
在 DBeaver 中为 SQLite 启用 SpatiaLite
数据库·sqlite
小马不起床3 天前
Django 后端实战指南_14:门店、省份、用户门店关系查询接口
数据库·django·sqlite
下页、再停留3 天前
【C#桌面客户端系列学习-14】SQLite数据库之增删改查完整示例
数据库·sqlite
weixin_382395235 天前
0-500 人工厂的生产 PMC 系统怎么做?基于 Tauri + SQLite 的性能架构实践与 5000 物料压测实录
数据库·架构·sqlite
winfredzhang5 天前
从零实现“照片按地理位置显示在矢量地图上”:Flask + SQLite + Leaflet 全栈实战
python·sqlite·flask
小马不起床6 天前
Django 后端实战指南_10:用户扩展档案信息表
python·django·sqlite
软件交付观察室6 天前
数据大屏总数与明细为什么对不上?2026项目开发排查指南
软件测试·数据库·sql·sqlite·数据可视化