0

http://missfeel.blog.163.com/blog/static/6768840220110201308929/

#include "stdafx.h"
#include <iostream>
#include <Windows.h>

extern "C"
{
#include "./sqlite3.h"
};
using namespace std;


#pragma comment(lib, "./sqlite3.lib")

//UTF-8到GB2312的转换
char* U2G(const char* utf8)
{
 int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
 wchar_t* wstr = new wchar_t[len+1];
 memset(wstr, 0, len+1);
 MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
 len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
 char* str = new char[len+1];
 memset(str, 0, len+1);
 WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
 if(wstr) delete[] wstr;
 return str;
}

//GB2312到UTF-8的转换
char* G2U(const char* gb2312)
{
 int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
 wchar_t* wstr = new wchar_t[len+1];
 memset(wstr, 0, len+1);
 MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
 len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
 char* str = new char[len+1];
 memset(str, 0, len+1);
 WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
 if(wstr) delete[] wstr;
 return str;
}


//sqlite3的回调函数
//sqlite 每查到一条记录,就调用一次这个回调
int LoadMyInfo(void *para, int n_column, char**column_value, char** column_name)
{
 //para是你在 sqlite3_exec 里传入的 void* 参数
 //通过para参数,你可以传入一些特殊的指针(比如类指针、结构指针),然后在这里面强制转\
 换成对应的类型(这里面是void*类型,必须强制转换成你的类型才可用)。然后操作这些数据
 //n_column是这一条记录有多少个字段 (即这条记录有多少列)
 //char**column_value 是个关键值,查出来的数据都保存在这里,它实际\
 上是个1维数组(不要以为是2维数组),每一个元素都是一个 char* 值,是一个字段内容(用\
 字符串来表示,以\0结尾)
  //char**column_name 跟 column_value是对应的,表示这个字段的字段名称
  //这里,我不使用 para 参数。忽略它的存在.
 int i;
 printf( "记录包含 %d 个字段\n", n_column);
 for(i=0; i<n_column; i++)
 {

//UTF-8转换为GB2312
  printf( "字段名:%s 字段值:%s\n",U2G(column_name[i]), U2G(column_value[i]));
 }
 printf("------------------\n");
 return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
 char *errmsg = NULL;
 sqlite3 *db =NULL;

//用的绝对路径测试数据库,呵呵
 int result = sqlite3_open("d:\\DB\\server.db3", &db);
 if (result != SQLITE_OK)
 {
  cout<<"失败!"<<endl;
  return -1;
 }
 cout<<"success!"<<endl;
 //开始查询数据库"
 char sql[100];
 sprintf(sql,"select * from user where name = '张三'");

//GB2312转换为UTF-8
 char * pSql = G2U(sql);
 result = sqlite3_exec(db, pSql, LoadMyInfo, NULL, &errmsg);
 if (result != SQLITE_OK)
 {
  cout<<"  查询失败!"<<endl;  
 }
 if (pSql)
 {
  delete pSql;

  pSql = NULL;
 }
 sqlite3_close(db);
 return 0;
}

 

 

转)QT中SQLite中文乱码的解决方案

今天看需求时发现代码里SQLite数据库竟然忘了加入对中文字符的支持,以前c++和c#中这种问题的解决方法倒是很熟了,但是qt 的很多接口还不太熟,于是请教google大神,网上用的最多的方案是使用QSqlQuery时将执行的字符串使用QObject::tr()转码。

由于SQLite内部编码是用utf8,而windows是采用GBK,所以需要对QString进行转码,方法如下:

QTextCodec::setCodecForTr(QTextCodec::codecForName(“UTF-8″));
QString querystr = QObject::tr(QString(“insert into Contact values(‘%1′)”).arg(entity->Name);

这样就将字符串转换为utf8格式,可以将中文字段正常插入到SQL中。

ps:一般的linux系统默认的编码是unicode,因此不需要第一条语句,不过我还没有亲自 试验过。

在使用过程中,我发现另一个问题,那就是采用上面的解决方案后,无论是在终端还是SQL管理器中查看执行结果,发现仍然出现乱码,经过debug发现问题出在QString 。虽然QString是不存在不支持中文的问题,但是在字符串中同时有中文字符和英文字符时,如:

“QString a= “中文/English”;

此时直接打印a,会显示乱码,需要指定QString的编码,虽然QString是采用unidoce保存字符的,但是不知道赋给的值是采用什么编码,于是默认是latin1编码,也就是将”中文/English”以latin的格式转换成unicode,于是打印中文时会乱码,我们需要告诉QString 这是什么格式的编码以便正确的转换:

QTextCodec::setCodecForCStrings(QTextCodec::codecForName(“GB2312″));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName(“UTF-8″));

视系统的编码环境2选1即可,指定了编码格式后,QString中的中文字符就可以正常显示了。

上面就是因为我的query语句使用QString.arg动态生成的,中文字符是在arg的参数中,因此需要指定编码让QString也直接支持中文。

关闭 返回顶部
联系我们
Copyright © 2011. 聚财吧. All rights reserved.