【存储】Cocos2d-x集成wxSQLite3


【说明】

Cocos2d-x已经集成了SQLite3,但是并未做加密处理,处于安全考虑,一般不会直接使用。wxSQLite3是一个开源项目,是对SQLite3的C++封装,并做了加密处理,使用起来也很方便。这里介绍我集成wxSQLite3的过程,期间参考了其他大神的文章,后面已做说明。


【下载】

http://sourceforge.net/projects/wxcode/files/Components/wxSQLite3/


【集成】

1. 下载wxSQLite3后解压,将 wxsqlite3-3.2.1\sqlite3\secure\src 文件夹拷贝到项目中。

2. 由于wxSQLite3内部已经引用,所以在Xcode中只需要引用 “sqlite3.h” 和 “sqlite3secure.c” 两个文件,引用其他文件会导致编译出错。

3. 由于我们需要用到加密功能,所以需要在 “sqlite3.h” 和 “sqlite3secure.c” 两个文件中都添加启用加密宏定义。这里我没有使用预编译宏定义的方式,是因为我更倾向于使用平台无关的方式。但是这里要注意添加的位置,否则可能会编译出错。

#ifndef SQLITE_HAS_CODEC
#define SQLITE_HAS_CODEC
#endif


4. 到这里引入就已经完成了,如果编译遇到 “SQLITE_USER_AUTHENTICATION” 报错,将报错位置“#if”全部改为“#ifdef”即可,其他地方如有类似错误也可这样解决。

5. 以上是在Xcode上的集成过程,对于Android平台,需要编写一个一个 Android.mk 文件。这段借鉴网上文章,我还没实践。

LOCAL_PATH := $(call my-dir)

#清理变量定义
include $(CLEAR_VARS)

#模块名称
LOCAL_MODULE := wxsqlite3_static

#库文件名称
LOCAL_MODULE_FILENAME := libwxsqlite3

#定义预编译宏
LOCAL_CFLAGS += -DSQLITE_HAS_CODEC  ##该宏用于开启加密功能,我已经把定义写到代码里了,这里可以不要

#源文件
LOCAL_SRC_FILES := src/sqlite3secure.c


LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src

#头文件目录
LOCAL_C_INCLUDES := $(LOCAL_PATH)/src

#构建静态库
include $(BUILD_STATIC_LIBRARY)
在 jni/Android.mk 中(不一定是这个,反正就是在应用的Android.mk中)添加引用:

<pre name="code" class="cpp">LOCAL_CFLAGS += -DSQLITE_HAS_CODEC                            #该宏用于开启加密功能  
  
LOCAL_WHOLE_STATIC_LIBRARIES += wxsqlite3_static         #引入静态库  
 
$(call import-module,../Classes/wxsqlite3)                              #引入模块 (Android.mk位置) 


 
 

【使用】

使用部分可以参考Cocos2d-x自带的 LocalStorage 类,加密功能需要在 “sqlite3_open()” 和 “sqlite3_close()” 之间调用 “sqlite3_key()” 设置密码。

        // SET KEY
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
        sqlite3_key(_db, key.c_str(), (int)key.size());
#endif


【代码】

最后附上我封(xiu)装(gai)的类,基本上都是 LocalStorage 的代码,只做了一点点修改。原本我是做成单例模式的,后来打算把集中存储合并到一个存储类里面,方便使用,就改成了普通类。前面才是重点,这部分不重要。

//====================================================================================
// LSqlite.h
// Local storage by sqlite3.
// Use wxsqlite3 in order to encrypt data.
// Created by Dolphin Lee.
//====================================================================================
#ifndef __L_SQLITE_H__
#define __L_SQLITE_H__

#include "cocos2d.h"
USING_NS_CC;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "sqlite3.h"
#else
#include "wxsqlite3/sqlite3.h"
#endif

//====================================================================================

class LSqlite
{
public:
    /**
     * Constructor function.
     */
    LSqlite();
    
    /**
     * Frees the allocated resources and close database.
     */
    ~LSqlite();
    
public:
    /**
     * Initializes the database. If path is null, it will create an in-memory DB.
     * @param filename    Name of database file. (like "data.db")
     * @param key         The key to encrypt database.
     */
    void init(const std::string& filename, const std::string& key);
    
    /**
     * Sets an item in the LS.
     * The item is divided into key and values.
     */
    void setItem(const std::string& key, const std::string& value);
    
    /**
     * Gets an item from the LS.
     * Will return the value according to key.
     */
    std::string getItem(const std::string& key);
    
    /**
     * Removes an item from the LS.
     * Will delete the value according to key.
     */
    void removeItem(const std::string& key);
    
protected:
    /**
     * Initializes the database. If path is null, it will create an in-memory DB.
     * @param fullpath    Full path with file name.
     * @param key         The key to encrypt database.
     */
    void initWithFullpath(const std::string& fullpath, const std::string& key);
    
    /**
     * Create table in the database.
     * This function has been invoked in init, you don't need to call.
     */
    void createTable();

private:
    int _initialized;
    sqlite3 *_db;
    sqlite3_stmt *_stmt_select;
    sqlite3_stmt *_stmt_remove;
    sqlite3_stmt *_stmt_update;
};
//====================================================================================

#endif
//====================================================================================
// LSqlite.cpp
//====================================================================================
#include "LSqlite.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//====================================================================================
// Create
//====================================================================================

/** constructors */
LSqlite::LSqlite()
{
    _initialized = 0;
    _db = nullptr;
    _stmt_select = nullptr;
    _stmt_remove = nullptr;
    _stmt_update = nullptr;
}

/** free database */
LSqlite::~LSqlite()
{
    if( _initialized )
    {
        sqlite3_finalize(_stmt_select);
        sqlite3_finalize(_stmt_remove);
        sqlite3_finalize(_stmt_update);
        
        sqlite3_close(_db);
        
        _initialized = 0;
    }
}

/** create table */
void LSqlite::createTable()
{
    const char *sql_createtable = "CREATE TABLE IF NOT EXISTS data(key TEXT PRIMARY KEY,value TEXT);";
    sqlite3_stmt *stmt;
    int ok=sqlite3_prepare_v2(_db, sql_createtable, -1, &stmt, NULL);
    ok |= sqlite3_step(stmt);
    ok |= sqlite3_finalize(stmt);
    
    if( ok != SQLITE_OK && ok != SQLITE_DONE)
    {
        printf("[sqlite3] Error in CREATE TABLE\n");
    }
}

/** init database */
void LSqlite::initWithFullpath( const std::string& fullpath, const std::string& key)
{
    if( ! _initialized )
    {
        int ret = 0;
        
        // OPEN DATABASE
        if (fullpath.empty())
        {
            ret = sqlite3_open(":memory:",&_db);
        }
        else
        {
            ret = sqlite3_open(fullpath.c_str(), &_db);
        }
        
        // SET KEY
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
        sqlite3_key(_db, key.c_str(), (int)key.size());
#endif
        
        // EXPAND FUNCTION
        //sqlite3_exec(_db, "PRAGMA synchronous = OFF", 0 ,0, 0); // 提交性能
        //sqlite3_exec(_db, "PRAGMA cache_size = 8000", 0 ,0, 0); // 加大缓存
        //sqlite3_exec(_db, "PRAGMA count_changes = 1", 0 ,0, 0); // 返回改变记录数
        //sqlite3_exec(_db, "PRAGMA case_sensitive_like = 1", 0 ,0, 0); // 支持中文LIKE查询
        
        // CREATE TABLE
        createTable();
        
        // SELECT
        const char *sql_select = "SELECT value FROM data WHERE key=?;";
        ret |= sqlite3_prepare_v2(_db, sql_select, -1, &_stmt_select, NULL);
        
        // REPLACE
        const char *sql_update = "REPLACE INTO data (key, value) VALUES (?,?);";
        ret |= sqlite3_prepare_v2(_db, sql_update, -1, &_stmt_update, NULL);
        
        // DELETE
        const char *sql_remove = "DELETE FROM data WHERE key=?;";
        ret |= sqlite3_prepare_v2(_db, sql_remove, -1, &_stmt_remove, NULL);
        
        if( ret != SQLITE_OK )
        {
            printf("[sqlite3] Error initializing DB\n");
            // report error
        }
        
        _initialized = 1;
    }
}

//====================================================================================
// Functions
//====================================================================================

/** init database */
void LSqlite::init(const std::string& filename, const std::string& key)
{
    std::string path = FileUtils::getInstance()->getWritablePath();
    path += filename;
    
    initWithFullpath(path, key);
}

/** sets an item in the LS */
void LSqlite::setItem( const std::string& key, const std::string& value)
{
    assert( _initialized );
    
    int ok = sqlite3_bind_text(_stmt_update, 1, key.c_str(), -1, SQLITE_TRANSIENT);
    ok |= sqlite3_bind_text(_stmt_update, 2, value.c_str(), -1, SQLITE_TRANSIENT);
    
    ok |= sqlite3_step(_stmt_update);
    
    ok |= sqlite3_reset(_stmt_update);
    
    if( ok != SQLITE_OK && ok != SQLITE_DONE)
    {
        printf("[sqlite3] Error in locaLSqlite.setItem()\n");
    }
}

/** gets an item from the LS */
std::string LSqlite::getItem( const std::string& key )
{
    assert( _initialized );
    
    std::string ret;
    int ok = sqlite3_reset(_stmt_select);
    
    ok |= sqlite3_bind_text(_stmt_select, 1, key.c_str(), -1, SQLITE_TRANSIENT);
    ok |= sqlite3_step(_stmt_select);
    const unsigned char *text = sqlite3_column_text(_stmt_select, 0);
    if (text)
    {
        ret = (const char*)text;
    }

    if( ok != SQLITE_OK && ok != SQLITE_DONE && ok != SQLITE_ROW)
    {
        printf("[sqlite3] Error in locaLSqlite.getItem()\n");
    }
    
    return ret;
}

/** removes an item from the LS */
void LSqlite::removeItem( const std::string& key )
{
    assert( _initialized );
    
    int ok = sqlite3_bind_text(_stmt_remove, 1, key.c_str(), -1, SQLITE_TRANSIENT);
    
    ok |= sqlite3_step(_stmt_remove);
    
    ok |= sqlite3_reset(_stmt_remove);
    
    if( ok != SQLITE_OK && ok != SQLITE_DONE)
    {
        printf("[sqlite3] Error in locaLSqlite.removeItem()\n");
    }
}

//====================================================================================
//
//====================================================================================


【参考】

http://blog.csdn.net/linchaolong/article/details/41286297

http://www.yiwuye.com/archives/cocos2d-x-encrpt-sqlite.html

http://www.cocoachina.com/bbs/read.php?tid=199953



猜你喜欢

转载自blog.csdn.net/ldpjay/article/details/46441617