最近在項(xiàng)目中用到了SQLite。主要是客戶端用到,這種小型內(nèi)嵌數(shù)據(jù)庫(kù)還是蠻實(shí)用的。
提起SQLite我不自覺的就想起了微軟出的ACCESS。他們兩個(gè)確實(shí)是有可比性的。曾經(jīng),小型網(wǎng)站數(shù)據(jù)庫(kù),ASP可以用到ACCESS。但是,PHP卻是沒有相對(duì)應(yīng)的解決方案,自從SQLite的出現(xiàn),給PHP提供了一個(gè)解決方案。
在客戶端里面,我用到的數(shù)據(jù)保存方案有:CSV、INI、XML。其中XML是最強(qiáng)大的,但是可惜的是我用的解析器是Tinyxml,實(shí)用tinyxml的初衷就是簡(jiǎn)單,只用于配置,所以再?gòu)?fù)雜的事情就有些應(yīng)付不過來。至少,邏輯上要復(fù)雜上許多。
我最近,看了迅雷,搜狗……一些軟件的目錄,都有一個(gè)sqlite3.dll。于是就去了解了下。貌似現(xiàn)在很多的im軟件用這個(gè)做客戶端數(shù)據(jù)庫(kù)的也多起來了。看起來這個(gè)項(xiàng)目還是不錯(cuò)的。
SQLite有好幾種版本,如果要想內(nèi)嵌到應(yīng)用程序當(dāng)中去,那就要用sqlite-amalgamation這個(gè)版本了。它就是一個(gè)頭文件,一個(gè)c的實(shí)現(xiàn)文件,這個(gè)文件里面有十多萬行代碼。我用VS2003編譯的時(shí)候,編譯器會(huì)提醒我,行數(shù)有些超長(zhǎng)了-_-!!
C++里面對(duì)SQLite的包裝類庫(kù)里面,我覺得SOCI算是很不錯(cuò)的,這個(gè)項(xiàng)目不僅僅是對(duì)SQLite進(jìn)行了包裝,而且對(duì)其他數(shù)據(jù)庫(kù)都有包裝,像MySQL、PostgreSQL、Oracle這些數(shù)據(jù)庫(kù)都支持,還支持ODBC。如果感興趣可以看我轉(zhuǎn)載的一篇博文:http://www.shnenglu.com/tx7do/archive/2009/11/27/102054.html
“工欲善其事,必先利其器。”
既然是數(shù)據(jù)庫(kù),那我自然要有工具能夠編輯數(shù)據(jù)庫(kù)了。我找了找SQLite的數(shù)據(jù)庫(kù)工具,一搜一大把。我試用了好多種,都不是很好用。最終才確定了SQLite Expert Professional,這款商業(yè)軟件。當(dāng)然,我很無恥的用了破解版。破解版在www.gougou.com里面就能搜索到。我是傾向于用開源軟件的,但是很無奈的是,雖然相關(guān)的工具很多很多,但是就沒有一款真正好用的。
我在用SQLite Expert創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候,發(fā)現(xiàn)有一個(gè)選擇編碼的選項(xiàng),但是很可惜的是全部都是UTF系的編碼……我習(xí)慣性的選擇了UTF8,這個(gè)也是它的默認(rèn)選項(xiàng)。我創(chuàng)建了一個(gè)測(cè)試的數(shù)據(jù)庫(kù),隨便弄了個(gè)表,打了幾個(gè)字,然后保存。再用VS2003做了一個(gè)測(cè)試程序,結(jié)果讀進(jìn)來的是亂碼。后來我把數(shù)據(jù)庫(kù)文件放到一個(gè)路徑里面有中文的路徑下,結(jié)果它找不到文件,看來它完完全全的使用了UTF字符,包括對(duì)路徑的處理。看起來,只能轉(zhuǎn)碼了。以下附上兩個(gè)Windows下的轉(zhuǎn)碼的方法:
std::string UTF8ToAnsi( const std::string& strIn, std::string& strOut )


{
WCHAR* strSrc = NULL;
TCHAR* szRes = NULL;

int i = MultiByteToWideChar(CP_UTF8, 0, strIn.c_str(), -1, NULL, 0);

strSrc = new WCHAR[i+1];
MultiByteToWideChar(CP_UTF8, 0, strIn.c_str(), -1, strSrc, i);

i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);

szRes = new TCHAR[i+1];
WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);

strOut = szRes;

delete[] strSrc;
delete[] szRes;

return strOut;
}

std::string AnsiToUTF8( const std::string& strIn, std::string& strOut )


{
WCHAR* strSrc = NULL;
TCHAR* szRes = NULL;

int len = MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strIn.c_str(), -1, NULL,0);

unsigned short* wszUtf8 = new unsigned short[len+1];
memset(wszUtf8, 0, len * 2 + 2);
MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strIn.c_str(), -1, (LPWSTR)wszUtf8, len);

len = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)wszUtf8, -1, NULL, 0, NULL, NULL);

char* szUtf8 = new char[len + 1];
memset(szUtf8, 0, len + 1);
WideCharToMultiByte (CP_UTF8, 0, (LPCWSTR)wszUtf8, -1, szUtf8, len, NULL,NULL);

strOut = szUtf8;

delete[] szUtf8;
delete[] wszUtf8;

return strOut;
}

這兩個(gè)方法可能不能直接編譯過,有一些自己的東西,需要稍事修改。
用AnisToUTF8將輸入的字符串全都轉(zhuǎn)換為UTF8。用UTF8ToAnis將所有輸出的字符串全部都轉(zhuǎn)化為多字節(jié)字符。
引用:
SQLite:http://www.sqlite.org/
SOCI:http://soci.sourceforge.net/
SQLite Expert Professional:http://www.sqliteexpert.com/