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的生命周期
关键注意点
- 确保你的SQLite数据库是UTF-8编码创建的(默认就是,不用额外设置)
- VC项目的字符集设置为Unicode字符集(因为CString默认是宽字符)
- 转换时必须指定
CP_UTF8编码,不能用默认的ANSI编码,否则中文会乱码
内容的提问来源于stack exchange,提问作者johnlu519
相关产品推荐
相关产品推荐

