顯示具有 sqlite 標籤的文章。 顯示所有文章
顯示具有 sqlite 標籤的文章。 顯示所有文章

[cocos2dx-JSB篇]sys.localStorage中文字變亂碼

文章撰寫日期︰2013/11/22 10:42
cocos2dx使用版本︰v 2.1.4

一、問題

今天在使用
sys.localStorage.setItem("mykey","我是中文");
然後使用
sys.localStorage.getItem("mykey");
欲取岀"我是中文"字串時,
Web端正常,
而Android/IOS端卻遇到了亂碼問題。

二、解決辦法

一看到上面的錯誤,
馬上就將問題點懷疑至JSB-binding身上。

在Android/IOS端若使用sys.localStorage來儲存資料,
Cocos2d-x會創建一個Native的Sqlite來儲存使用。

初步懷疑這是Sqlite的中文utf-8支援問題,
後來開啟了這個資料庫來看,
發現中文是有正常存入的。
因此問題是發生在取岀中文字串時的方法有誤

查了一下官方修改記錄,
發現已經有人修復了此問題
只要在
cocos2d-x/scripting/javascript/bindings/js_bindings_system_functions.cpp裡
添加一個include
#include "ScriptingCore.h"

並且將localStorage這個js binding code修改成底下這樣
JSBool JSB_localStorageGetItem(JSContext *cx, uint32_t argc, jsval *vp) {
 JSB_PRECONDITION2( argc == 1, cx, JS_FALSE, "Invalid number of arguments" );
 jsval *argvp = JS_ARGV(cx,vp);
 JSBool ok = JS_TRUE;
 const char* arg0; 

 ok &= jsval_to_charptr( cx, *argvp++, &arg0 );
 JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments");
 const char* ret_val;

 ret_val = localStorageGetItem((char*)arg0  );

// jsval ret_jsval = charptr_to_jsval( cx, ret_val);
    jsval ret_jsval = c_string_to_jsval(cx, ret_val ? ret_val : "");//加入這行
    
 JS_SET_RVAL(cx, vp, ret_jsval );

 return JS_TRUE;
}

中文亂碼問題即可解決。

這個問題官方一直到Cocos2dx3.0 alpha1才正式修復Merge進Cocos2d-x源碼中,
因此若您使用cocos2d-x2.1.4/2.1.5/3.0alpha0/3.0 alpha0,
應該都會遭遇此問題。

關鍵字︰
乱码,中文

[Android篇]SQLite在Android無法讀取(返回錯誤碼14)的決解方案

文章撰寫日期︰2013/03/19 13:46
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

在Xcode中,使用
sqlite3 *pDB = NULL;//資料庫指針

string  szResPath(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("millionschool.sqlite"));
sqlite3_open(szResPath.c_str(), &pDB);
就能順利將Resources資料夾下的millionschool.sqlite打開並使用。

但是,
Android卻無法這樣子打開,
返回了錯誤碼14

二、解決方法

經爬文後發現,
sqlite3 *pDB = NULL;//資料庫指針CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("millionschool.sqlite"));
這個取到的路徑在Android下會被壓縮,
無法正常存取。
解決方法只有將sqlite檔案複製至可存取的Android資料夾方可使用。
CCFileUtils::sharedFileUtils()->getWriteablePath();
此方法在Android底下會取到本機裡data\data\package_name\這個目錄,
於是我們將assets底下的sqlite複製到這邊來。
        sqlite3 *pDB = NULL;//資料庫指針
        char * errMsg = NULL;//錯誤訊息
        std::string sqlstr;//SQL指令
        int result;//sqlite3_exec返回值
        
        string  szResPath(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("millionschool.sqlite"));//IOS可以這樣用,但Android卻不行

        //取得Android可以使用的data\data\package_name資料夾
        string dbPath = CCFileUtils::sharedFileUtils()->getWriteablePath();
        dbPath.append("millionschool.sqlite");

        //將資料寫入串流
        unsigned long tmpSize;
        unsigned char* dbData = CCFileUtils::sharedFileUtils()->getFileData(szResPath.c_str(), "rb", &tmpSize);
        FILE *fp = fopen(dbPath.c_str(), "wb");
        fwrite(dbData, tmpSize, 1, fp);
        fclose(fp);

        //將資料庫打開來看看
        result = sqlite3_open(dbPath.c_str(), &pDB);
        
        if( result != SQLITE_OK ){
            CCLog( "打開資料庫失敗,錯誤碼:%d ,錯誤原因:%s\n" , result, errMsg );
        }else{
            CCLog( "打開資料庫成功!" );
        }
成功了! 讀到資料庫了!