You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite+VC2015 UTF-8项目中文存储及字符串转换问题求助

解决VC2015中CString转UTF-8 char*适配SQLite的问题

嘿,我帮你搞定这个VC2015+SQLite的中文存储问题!你的核心痛点是宽字符CString转UTF-8编码的char*,因为SQLite默认用UTF-8处理字符串,而sqlite3_exec只接受char*类型的SQL语句。下面给你几个实用的解决方案,还会顺便解决潜在的SQL注入风险:

方案一:用ATL转换宏CA2A(最简单)

VC2015自带ATL库,CA2A可以轻松把宽字符(wchar_t*)转成指定编码的多字节字符串,这里我们指定CP_UTF8编码:

// 假设m_szName是用户输入的CString变量
CA2A utf8CityName(m_szName, CP_UTF8);

// 拼接SQL语句(注意:如果城市名包含单引号会有问题,后面会说更安全的方法)
stringstream sql;
sql << "INSERT OR REPLACE INTO Cities (Id, Desc) VALUES ('1001','" << utf8CityName.m_psz << "')";

// 执行SQL
int rc = sqlite3_exec(db, sql.str().c_str(), NULL, NULL, NULL);

CA2A会自动管理转换后的内存,不用手动释放,非常省心。

方案二:手动调用WideCharToMultiByte(无需ATL)

如果你不想依赖ATL库,可以用Windows API手动转换:

CString m_szName = L"用户输入的城市名";

// 先计算UTF-8字符串所需的缓冲区大小
int utf8BufSize = WideCharToMultiByte(CP_UTF8, 0, m_szName, -1, NULL, 0, NULL, NULL);
char* utf8CityName = new char[utf8BufSize];

// 执行转换
WideCharToMultiByte(CP_UTF8, 0, m_szName, -1, utf8CityName, utf8BufSize, NULL, NULL);

// 拼接并执行SQL
stringstream sql;
sql << "INSERT OR REPLACE INTO Cities (Id, Desc) VALUES ('1001','" << utf8CityName << "')";
sqlite3_exec(db, sql.str().c_str(), NULL, NULL, NULL);

// 记得手动释放内存
delete[] utf8CityName;

更安全的方案:用SQLite参数绑定(避免SQL注入)

直接拼接字符串有SQL注入风险(比如用户输入北京' OR 1=1--),而且如果城市名包含单引号,SQL语句会直接报错。推荐用SQLite的预编译语句+参数绑定:

sqlite3_stmt* pStmt = nullptr;
const char* sqlTemplate = "INSERT OR REPLACE INTO Cities (Id, Desc) VALUES (?, ?)";

// 预编译SQL语句
int rc = sqlite3_prepare_v2(db, sqlTemplate, -1, &pStmt, NULL);
if (rc != SQLITE_OK) {
    // 处理错误
    return;
}

// 绑定第一个参数(Id,字符串类型)
sqlite3_bind_text(pStmt, 1, "1001", -1, SQLITE_STATIC);

// 把CString转成UTF-8后绑定第二个参数(Desc)
CA2A utf8CityName(m_szName, CP_UTF8);
sqlite3_bind_text(pStmt, 2, utf8CityName.m_psz, -1, SQLITE_TRANSIENT);

// 执行语句
rc = sqlite3_step(pStmt);
if (rc != SQLITE_DONE) {
    // 处理执行错误
}

// 释放预编译语句
sqlite3_finalize(pStmt);
  • SQLITE_STATIC:表示参数是常量字符串,SQLite不需要复制它
  • SQLITE_TRANSIENT:表示SQLite需要自己复制一份参数数据,我们不需要保持utf8CityName的生命周期

关键注意点

  1. 确保你的SQLite数据库是UTF-8编码创建的(默认就是,不用额外设置)
  2. VC项目的字符集设置为Unicode字符集(因为CString默认是宽字符)
  3. 转换时必须指定CP_UTF8编码,不能用默认的ANSI编码,否则中文会乱码

内容的提问来源于stack exchange,提问作者johnlu519

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:40:01