Ppeixianzhonglicense and 53.4
7db74aee创建于 2024年7月19日历史提交

kv4cj库

介绍

MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。参考地址:https://github.com/Tencent/MMKV

MMKV

前置条件:NA

场景:

约束:

  1. cryptKey 最大长度为 16个字节的字符串

性能:NA

可靠性:NA

1. 全局常量及类型

public type MMKVLogLevel = Int32
public let MMKVLogDebug: MMKVLogLevel = 0 // not available for release/product build
public let MMKVLogInfo: MMKVLogLevel = 1  // default level
public let MMKVLogWarning: MMKVLogLevel = 2
public let MMKVLogError: MMKVLogLevel = 3
public let MMKVLogNone: MMKVLogLevel = 4 // special level used to disable all log messages

public type MMKVMode = UInt32
public let MMKV_SINGLE_PROCESS: MMKVMode = 0x1 // 单进程模式,默认使用模式
public let MMKV_MULTI_PROCESS: MMKVMode = 0x2 // 多进程模式

public type MMKVRecoverStrategic = Int32
public let OnErrorDiscard: MMKVRecoverStrategic = 0
public let OnErrorRecover: MMKVRecoverStrategic = 1

public type MMKVErrorType = Int32
public let MMKVCRCCheckFail: MMKVErrorType = 0
public let MMKVFileLength: MMKVErrorType = 1

public type MMKVRecoverStrategic = Int32
public let OnErrorDiscard: MMKVRecoverStrategic = 0
public let OnErrorRecover: MMKVRecoverStrategic = 1

2. 初始化

2.1 主要接口

public class MMKV {
    /*
    * 提供MMKV初始化接口,设定 MMKV 的根目录,在获取任何MMKV实例之前调用此函数
    * 使用logLevel=MMKVLogInfo,handler为空初始化
    *
    * 参数 - rootDir mmkv目录
    *
    * 返回值 - Unit
    */
    public static func initializeMMKV(rootDir: String): Unit

    /*
    * 提供MMKV初始化接口,设定 MMKV 的根目录,在获取任何MMKV实例之前调用此函数
    * 使用handler为空初始化
    *
    * 参数 - rootDir mmkv目录
    * 参数 - logLevel log等级
    *
    * 返回值 - Unit
    */
    public static func initializeMMKV(rootDir: String, logLevel: MMKVLogLevel): Unit

    /*
    * 提供MMKV初始化接口,设定 MMKV 的根目录,在获取任何MMKV实例之前调用此函数
    * 使用logLevel=MMKVLogInfo
    *
    * 参数 - rootDir mmkv目录
    * 参数 - handler log处理函数
    *
    * 返回值 - Unit
    */
    public static func initializeMMKV(rootDir: String, handler: MMKVHandler): Unit

    /*
    * 提供MMKV初始化接口,设定 MMKV 的根目录,在获取任何MMKV实例之前调用此函数
    *
    * 参数 - rootDir mmkv目录
    * 参数 - logLevel log等级,默认MMKVLogInfo
    * 参数 - handler log处理函数
    *
    * 返回值 - Unit
    */
    public static func initializeMMKV(rootDir: String, logLevel: MMKVLogLevel, handler: MMKVHandler): Unit

    /*
    * 全局的实例
    *
    *
    * 参数 - mode mmkv 模式 
    * 参数 - cryptKey 加密秘钥,最大16个字节,超过16个字节,截取前16个字节
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func defaultMMKV(mode: MMKVMode, cryptKey: String): MMKV

    /*
    * 创建全局的实例
    * 使用cryptKey=null,创建实例
    *
    * 参数 - mode mmkv 模式
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func defaultMMKV(mode: MMKVMode): MMKV

    /*
    * 创建全局的实例  mode mmkv 模式 默认MMKV_SINGLE_PROCESS = 0x1,cryptKey=null
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func defaultMMKV(): MMKV

    /*
    * 创建自己实例
    *
    * 参数 - mmapID
    * 参数 - mode mmkv 模式
    * 参数 - cryptKey 加密秘钥,最大16个字节,超过16个字节,截取前16个字节
    * 参数 - rootPath mmkv路径
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func mmkvWithID(mmapID: String, mode: MMKVMode, cryptKey: String, rootPath: String): MMKV

    /*
    * 创建自己实例,使用rootPath为null
    *
    * 参数 - mmapID
    * 参数 - mode mmkv 模式
    * 参数 - cryptKey 加密秘钥 ,最大16个字节,超过16个字节,截取前16个字节
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func mmkvWithID(mmapID: String, mode: MMKVMode, cryptKey: String): MMKV

    /*
    * 创建自己实例,使用 cryptKey = null,rootPath = null
    *
    * 参数 - mmapID
    * 参数 - mode mmkv 模式
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func mmkvWithID(mmapID: String, mode: MMKVMode): MMKV

    /*
    * 创建自己实例,使用mode: MMKV_SINGLE_PROCESS= 0x1,cryptKey =null
    *
    * 参数 - mmapID
    * 参数 - 参数 - rootPath mmkv路径
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func mmkvWithID(mmapID: String, rootPath: String): MMKV

    /*
    * 创建自己实例,使用mode: MMKV_SINGLE_PROCESS= 0x1, cryptKey =null,rootPath =null
    *
    * 参数 - mmapID
    *
    * 异常 - 1. 没有在此之前调用MMKV.initializeMMKV()将抛出MMKVException异常
    *        2. 返回MMKV实例为空,抛出MMKVException异常
    *
    * 返回值 - MMKV
    */
    public static func mmkvWithID(mmapID: String): MMKV
}

2.2 示例

testInit.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

main() {
    MMKV.initializeMMKV("rootdir")
    var mmkv = MMKV.mmkvWithID("MyID")
    return 0
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testInit.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/MyID
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/MyID.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [MyID] with 133 actual size, file size 4096, InterProcess 0, meta info version:3
[I] <MMKV_IO.cpp:86::loadFromFile> loading [MyID] with crc 621142152 sequence 1 version 3
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [MyID] with 3 key-values

3. 存取key-value

3.1 主要接口

public class MMKV {
    /*
    * 存储bool类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: Bool): Bool

    /*
    * 读取bool类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值 默认false(如果key为空,返回默认值)
    *
    * 返回值 - bool
    */
    public func getBool(key: String, defaultValue!: Bool = false): Bool

    /*
    * 存储Int32类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: Int32): Bool

    /*
    * 读取Int32类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值 默认0(如果key为空或不存在,返回默认值)
    *
    * 返回值 - Int32
    */
    public func getInt32(key: String, defaultValue!: Int32 = 0): Int32

    /*
    * 存储UInt32类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: UInt32): Bool

    /*
    * 读取UInt32类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值 默认0(如果key为空或不存在,返回默认值)
    *
    * 返回值 - UInt32
    */
    public func getUInt32(key: String, defaultValue!: UInt32 = 0): UInt32

    /*
    * 存储bool类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: Int64): Bool

    /*
    * 读取Int64类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值 默认0(如果key为空或不存在,返回默认值)
    *
    * 返回值 - Int64
    */
    public func getInt64(key: String, defaultValue!: Int64 = 0): Int64

    /*
    * 存储UInt64类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: UInt64): Bool

    /*
    * 读取UInt64类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值 默认0(如果key为空或不存在,返回默认值)
    *
    * 返回值 - UInt64
    */
    public func getUInt64(key: String, defaultValue!: UInt64 = 0): UInt64

    /*
    * 存储Float32类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: Float32): Bool

    /*
    * 读取Float32类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值 默认0.0(如果key为空或不存在,返回默认值)
    *
    * 返回值 - Float32
    */
    public func getFloat32(key: String, defaultValue!: Float32 = 0.0): Float32

    /*
    * 存储Float64类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: Float64): Bool

    /*
    * 读取Float64类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值 默认0.0(如果key为空或不存在,返回默认值)
    *
    * 返回值 - Float64
    */
    public func getFloat64(key: String, defaultValue!: Float64 = 0.0): Float64

    /*
    * 存储String类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: String): Bool

    /*
    * 读取string类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值,默认""(如果key为空或不存在,返回默认值)
    *
    * 返回值 - String
    */
    public func getString(key: String, defaultValue!: String = ""): String

    /*
    * 存储Array<Byte>类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: Array<Byte>): Bool

    /*
    * 读取getBytes类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值,默认Array<Byte>()(如果key为空或不存在,返回默认值)
    *
    * 返回值 - Array<Byte>
    */
    public func getBytes(key: String, defaultValue!: Array<Byte> = Array<Byte>()): Array<Byte>

    /*
    * 存储HashSet<String>类型的key-value值
    *
    * 参数 - key
    * 参数 - value
    *
    * 返回值 - bool 存储成功返回true ,失败返回false(比如如果key为空,返回false)
    */
    public func set(key: String, value: HashSet<String>): Bool

    /*
    * 读取HashSet<String>类型的key-value值
    *
    * 参数 - key
    * 参数 - defaultValue 默认返回值,默认HashSet<String>()(如果key为空或不存在,返回默认值)
    *
    * 返回值 - HashSet<String>
    */
    public func getStringSet(key: String, defaultValue!: HashSet<String> = HashSet<String>()): HashSet<String>
}

3.2 示例

testSetGet.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

main() {
    MMKV.initializeMMKV("rootdir")
    var kv = MMKV.mmkvWithID("MyID")
    kv.set("bool", true)
    var value = kv.getBool("bool")
    println(value)

    kv.set("int32", 0x11223344)
    var iValue = kv.getInt32("int32")
    println(iValue)

    kv.set("string", "Hello from mmkv")
    var str = kv.getString("string")
    println(str)

    return 0
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testSetGet.cj -o main

执行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/MyID
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/MyID.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [MyID] with 90 actual size, file size 4096, InterProcess 0, meta info version:3
[I] <MMKV_IO.cpp:86::loadFromFile> loading [MyID] with crc 4094497785 sequence 1 version 3
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [MyID] with 3 key-values
true
287454020
Hello from mmkv

4 清理删除关闭操作

4.1 主要接口

public class MMKV {
    /*
    * 根据键值删除值,多个键值操作
    *
    * 参数 - arrKeys 需要删除的key
    *
    * 返回值 - Unit
    */
    public func removeValuesForKeys(arrKeys: Array<String>): Unit

    /*
    * 根据键值删除值,单个键值操作
    *
    * 参数 - key 需要删除的key
    *
    * 返回值 - Unit
    */
    public func removeValueForKey(key: String): Unit

    /*
    * 删除所有key-value对, 删除键值后MMKV的大小不会减小
    *
    * 返回值 - Unit
    */
    public func clearAll(): Unit

    /*
    * 清理mmkv磁盘占用
    *
    * 返回值 - Unit
    */
    public func trim(): Unit

    /*
    * 关闭实例,实例在不久的将来不再需要,则调用此方法
    *
    * 返回值 - Unit
    */
    public func close(): Unit

    /*
    * 清理内存缓存,如果面临内存警告,调用这个方法。任何对实例的后续调用将再次从file中加载所有key-value
    *
    * 返回值 - Unit
    */
    public func clearMemoryCache(): Unit

    /*
    * 同步内容,内存映射文件的方式将修改的内容同步到硬盘之上
    *
    * 返回值 - Unit
    */
    public func sync(): Unit

    /*
    * 同步内容,内存映射文件的方式将修改的内容同步到硬盘之上
    *
    * 返回值 - Unit
    */
    public func async(): Unit

    /*
    * 销毁mmkv,应用终止时调用
    *
    * 返回值 - Unit
    */
    public static func onExit(): Unit
}

4.2 示例

testRemove.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

func test_removeValueForKey1(kv: MMKV): Int64 {
    let key: String = "key"
    let value: String = "test_removeValueForKey1"

    var ret = kv.set(key, value)
    if (ret == false) {
        return -1
    }

    kv.removeValueForKey(key)
    var out = kv.getString("key")
    if (out == value) {
        return -1
    }

    return 0
}

main(): Int64 {
    var ret = 0
    MMKV.initializeMMKV("rootdir")
    var kv: MMKV = MMKV.mmkvWithID("test_removeValueForKey")
    ret = test_removeValueForKey1(kv)
    if (ret == -1) {
        return ret
    }

    return ret
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testRemove.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/test_removeValueForKey
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/test_removeValueForKey.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test_removeValueForKey] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test_removeValueForKey] with 0 key-values
[I] <MMKV_IO.cpp:451::writeActualSize> [test_removeValueForKey] increase sequence to 1, crc 1285129681, actualSize 4

5 获取mmkv根路径

5.1 主要接口

public class MMKV {
        /*
    * 获取mmkv根路径
    *
    * 返回值 - MMKVPath_t
    */
    public static func getRootDir(): String
}

5.2 示例

testRootdir.cj

import kv4cj.*

main(): Int64 {
    MMKV.initializeMMKV("rootdir")
    var kv: MMKV = MMKV.mmkvWithID("test_getRootDir")
    if (MMKV.getRootDir() != "rootdir") {
        return -1
    }

    return 0
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testRootdir.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/test_getRootDir
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/test_getRootDir.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test_getRootDir] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test_getRootDir] with 0 key-valuesxxxxxxxxxx [I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/test_getRootDir[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/test_getRootDir.crc[I] <MMKV_IO.cpp:81::loadFromFile> loading [test_getRootDir] with 0 actual size, file size 4096, InterProcess 0, meta info version:0[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test_getRootDir] with 0 key-values0

6 检测MMKV文件是否有效

6.1 主要接口

public class MMKV {
    /*
    * 检测MMKV文件是否有效
    * 不要用它来检查实例是否存在,不存在的实例结果是未知的。
    *
    * 参数 - mmapID mmkv实例
    *
    * 返回值 - Bool
    */
    public static func isFileValid(mmapID: String): Bool

    /*
    * 检测MMKV文件是否有效
    * 不要用它来检查实例是否存在,不存在的实例结果是未知的。
    *
    * 参数 - mmapID mmkv实例
    * 参数 - MMKV实例的文件夹
    *
    * 返回值 - Bool
    */
    public static func isFileValid(mmapID: String, rootPath: String): Bool
}

6.2 示例

testCheckFile.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*
import std.fs.*

main(): Int64 {
    MMKV.initializeMMKV("rootdir")
    var kv: MMKV = MMKV.mmkvWithID("test_isFileValid")
    for (i in 0..100) {
        var key = "key-" + i.toString()
        var value = "string-" + i.toString()
        var ret = kv.set(key, value)
        if (ret == false) {
            return -1
        }
    }

    if (!MMKV.isFileValid("test_isFileValid")) {
        return -1
    }

    File.delete("rootdir/test_isFileValid.crc")
    if (MMKV.isFileValid("test_isFileValid")) {
        return -1
    }

    return 0
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testCheckFile.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/test_isFileValid
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/test_isFileValid.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test_isFileValid] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test_isFileValid] with 0 key-values
[I] <MMKV_IO.cpp:451::writeActualSize> [test_isFileValid] increase sequence to 1, crc 1285129681, actualSize 4

7 获取内存相关信息

7.1 主要接口

public class MMKV {
    /*
    * 获取内存分页大小
    *
    * 返回值 - Int64
    */
    public static func pageSize(): Int64

    /*
    * 返回键值的实际大小消耗
    *
    * 参数 - key
    * 参数 - actualSize true:值的实际长度,false:值的实际存储消耗
    *
    * 返回值 - UInt64  返回的size大小
    */
    public func getValueSize(key: String, actualSize: Bool): UInt64

    /*
    * 判断是否存在这个key-value
    *
    * 参数 - key
    * 返回值 - Bool  返回是否存在这个key
    */
    public func containsKey(key: String): Bool

    /*
    * 获取key-value的数量
    *
    * 返回值 - UInt64  返回键值对个数
    */
    public func count(): UInt64

    /*
    * 返回mmkv实例文件大小
    *
    * 返回值 - UInt64
    */
    public func totalSize(): UInt64

    /*
    * 获取mmkv实例实际使用大小
    *
    * 返回值 - UInt64
    */
    public func actualSize(): UInt64

    /*
    * 获取所有的key
    *
    * 返回值 - HashSet<String>  返回所有key的HashSet
    */
    public func allKeys():HashSet<String>

    /*
    * 获取mmkv实例ID
    *
    * 返回值 - String
    */
    public func mmapID(): String
}

7.2 示例

testMemory.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

public func allKeys_test00(kv:MMKV): Bool {
    kv.set("set0", Float64(6437347329.943287))
    kv.set("set1", "hello cangjie allKeys_00")
    kv.set("set2", Int32(-444))
    kv.set("set3", UInt64(8989898))
    var set: HashSet<String> = HashSet<String>()
    set.put("set0")
    set.put("set1")
    set.put("set2")
    set.put("set3")
    var allKeys_kv: HashSet<String> = kv.allKeys()

    if (allKeys_kv != set) {
        return false
    }
    return true
}
main(): Unit {
    MMKV.initializeMMKV("rootdir")
    var kv = MMKV.mmkvWithID("test")
    println(MMKV.pageSize())
    if (allKeys_test00(kv) != true) {
        println("false")
    } else {
    	print("true")
    }
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testMemory.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/test
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/test.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test] with 0 key-values
4096
[I] <MMKV_IO.cpp:451::writeActualSize> [test] increase sequence to 1, crc 1285129681, actualSize 4

8. 备份和恢复mmkv实例

8.1 主要接口

public class MMKV {
    /*
    * 将一个 MMKV 实例备份到 dstDir
    *
    * 参数 - mmapID mmkv实例
    * 参数 - dstDir 备份目标目录
    *
    * 返回值 - Bool 备份成功返回true,备份失败返回false
    */
    public static func backupOneToDirectory(mmapID: String, dstDir: String): Bool

    /*
    * 将一个 MMKV 实例备份到 dstDir
    *
    * 参数 - mmapID mmkv实例
    * 参数 - dstDir 备份目标目录
    * 参数 - rootPath MMKV 自定义根路径
    *
    * 返回值 - Bool 备份成功返回true,备份失败返回false
    */
    public static func backupOneToDirectory(mmapID: String, dstDir: String, rootPath: String): Bool

    /*
    * 从 srcDir 恢复一个 MMKV 实例
    *
    * 参数 - mmapID mmkv实例
    * 参数 - srcDir 恢复源目录
    *
    * 返回值 - Bool 恢复成功返回true,恢复失败返回false
    */
    public static func restoreOneFromDirectory(mmapID: String, srcDir: String): Bool

    /*
    * 从 srcDir 恢复一个 MMKV 实例
    *
    * 参数 - mmapID mmkv实例
    * 参数 - srcDir 恢复源目录
    * 参数 - rootPath MMKV 自定义根路径
    *
    * 返回值 - Bool 恢复成功返回true,恢复失败返回false
    */
    public static func restoreOneFromDirectory(mmapID: String, srcDir: String, rootPath: String): Bool

    /*
    * 将所有 MMKV 实例备份到 dstDir
    *
    * 参数 - dstDir 备份目标目录
    *
    * 返回值 - UInt64 成功备份 MMKV 个数
    */
    public static func backupAllToDirectory(dstDir: String): UInt64

    /*
    * 将所有 MMKV 实例备份到 dstDir
    *
    * 参数 - dstDir 备份目标目录
    * 参数 - rootPath MMKV 自定义根路径
    *
    * 返回值 - UInt64 成功备份 MMKV 个数
    */
    public static func backupAllToDirectory(dstDir: String, rootPath: String): UInt64

    /*
    * 从 srcDir 恢复所有 MMKV 实例
    *
    * 参数 - srcDir 恢复源目录
    *
    * 返回值 - UInt64 成功恢复 MMKV 个数
    */
    public static func restoreAllFromDirectory(srcDir: String): UInt64

    /*
    * 从 srcDir 恢复所有 MMKV 实例
    *
    * 参数 - srcDir 恢复源目录
    * 参数 - rootPath MMKV 自定义根路径
    *
    * 返回值 - UInt64 成功恢复 MMKV 个数
    */
    public static func restoreAllFromDirectory(srcDir: String, rootPath: String): UInt64
}

8.2 示例

testBackupAndRestore.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

func setValue(mmkvID: String): Unit {
    var kv: MMKV = MMKV.mmkvWithID(mmkvID)
    kv.set("set0", false)
    kv.set("set1", Int32(-444))
    kv.set("set2", UInt32(555))
    kv.set("set3", Int64(-666))
    kv.set("set4", UInt64(777))
    kv.set("set5", Float32(0.888))
    kv.set("set6", Float64(0.999))
    kv.set("set7", "hello cangjie")
}

main(): Int64 {
    var rootDir = "/tmp/mmkv"
    var backupDir = "/tmp/mmkv_backup"
    var ret = 0

    MMKV.initializeMMKV(rootDir)
    setValue("test/Encrypt")
    MMKV.backupOneToDirectory("test/Encrypt", backupDir)
    MMKV.restoreOneFromDirectory("test/Encrypt", backupDir)
    var kv: MMKV = MMKV.mmkvWithID("test/Encrypt")
    println(kv.getInt32("set1"))

    setValue("test1")
    setValue("test2")

    var count = MMKV.backupAllToDirectory(backupDir)
    if (count != 3) {
        return -1
    }
    count = MMKV.restoreAllFromDirectory(backupDir)
    if (count != 3) {
        return -1
    }
    kv = MMKV.mmkvWithID("test1")
    println(kv.getInt32("set1"))

    return ret
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testBackupAndRestore.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: /tmp/mmkv
[I] <MemoryFile.cpp:97::open> open fd[0x3], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:97::open> open fd[0x4], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test/Encrypt] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test/Encrypt] with 0 key-values
[I] <MMKV_IO.cpp:451::writeActualSize> [test/Encrypt] increase sequence to 1, crc 1285129681, actualSize 4
[I] <MMKV.cpp:1044::backupOneToDirectory> backup one cached mmkv[test/Encrypt] from [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81]
[I] <MemoryFile.cpp:97::open> open fd[0x6], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81 to fd[5] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x6], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/MMKV.o4Wd4g]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81] finish.
[I] <MemoryFile.cpp:97::open> open fd[0x6], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc to fd[5] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x6], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc] to [/tmp/MMKV.Dyn1Rd]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc] to [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc] finish.
[I] <MMKV.cpp:1055::backupOneToDirectory> finish backup one mmkv[test/Encrypt], ret: 1
[I] <MMKV.cpp:1205::restoreOneFromDirectory> restore one cached mmkv[test/Encrypt] from [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81]
[I] <MemoryFile.cpp:97::open> open fd[0x5], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81 to fd[3] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x5], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:97::open> open fd[0x5], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc to fd[4] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x5], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MMKV.cpp:290::clearMemoryCache> clearMemoryCache [test/Encrypt]
[I] <MemoryFile.cpp:103::close> closing fd[0x3], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:97::open> open fd[0x3], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test/Encrypt] with 103 actual size, file size 4096, InterProcess 0, meta info version:3
[I] <MMKV_IO.cpp:86::loadFromFile> loading [test/Encrypt] with crc 2531236140 sequence 1 version 3
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test/Encrypt] with 8 key-values
[I] <MMKV.cpp:1224::restoreOneFromDirectory> finish restore one mmkv[test/Encrypt], ret: 1
-444
[I] <MemoryFile.cpp:97::open> open fd[0x5], /tmp/mmkv/test1
[I] <MemoryFile.cpp:97::open> open fd[0x6], /tmp/mmkv/test1.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test1] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test1] with 0 key-values
[I] <MMKV_IO.cpp:451::writeActualSize> [test1] increase sequence to 1, crc 1285129681, actualSize 4
[I] <MemoryFile.cpp:97::open> open fd[0x7], /tmp/mmkv/test2
[I] <MemoryFile.cpp:97::open> open fd[0x8], /tmp/mmkv/test2.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test2] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test2] with 0 key-values
[I] <MMKV_IO.cpp:451::writeActualSize> [test2] increase sequence to 1, crc 1285129681, actualSize 4
[I] <MMKV.cpp:1044::backupOneToDirectory> backup one cached mmkv[test2] from [/tmp/mmkv/test2] to [/tmp/mmkv_backup/test2]
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv/test2
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/test2 to fd[9] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv/test2
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/test2] to [/tmp/MMKV.g9I7Ga]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/test2] to [/tmp/mmkv_backup/test2] finish.
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv/test2.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/test2.crc to fd[9] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv/test2.crc
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/test2.crc] to [/tmp/MMKV.Vw2fw7]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/test2.crc] to [/tmp/mmkv_backup/test2.crc] finish.
[I] <MMKV.cpp:1055::backupOneToDirectory> finish backup one mmkv[test2], ret: 1
[I] <MMKV.cpp:1044::backupOneToDirectory> backup one cached mmkv[test1] from [/tmp/mmkv/test1] to [/tmp/mmkv_backup/test1]
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv/test1
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/test1 to fd[9] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv/test1
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/test1] to [/tmp/MMKV.kDNCl4]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/test1] to [/tmp/mmkv_backup/test1] finish.
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv/test1.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/test1.crc to fd[9] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv/test1.crc
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/test1.crc] to [/tmp/MMKV.XuZ0a1]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/test1.crc] to [/tmp/mmkv_backup/test1.crc] finish.
[I] <MMKV.cpp:1055::backupOneToDirectory> finish backup one mmkv[test1], ret: 1
[I] <MMKV.cpp:1044::backupOneToDirectory> backup one cached mmkv[4e566463fff4756aa8634a1f260d5f81] from [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81]
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81 to fd[9] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/MMKV.eJXC0X]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81] finish.
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc to fd[9] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MemoryFile.cpp:455::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc] to [/tmp/MMKV.6jygQU]
[I] <MemoryFile.cpp:458::copyFile> copyfile [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc] to [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc] finish.
[I] <MMKV.cpp:1055::backupOneToDirectory> finish backup one mmkv[4e566463fff4756aa8634a1f260d5f81], ret: 1
[I] <MMKV.cpp:1205::restoreOneFromDirectory> restore one cached mmkv[test2] from [/tmp/mmkv_backup/test2] to [/tmp/mmkv/test2]
[I] <MemoryFile.cpp:97::open> open fd[0x9], /tmp/mmkv_backup/test2
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/test2 to fd[7] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x9], /tmp/mmkv_backup/test2
[I] <MemoryFile.cpp:97::open> open fd[0x9], /tmp/mmkv_backup/test2.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/test2.crc to fd[8] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x9], /tmp/mmkv_backup/test2.crc
[I] <MMKV.cpp:290::clearMemoryCache> clearMemoryCache [test2]
[I] <MemoryFile.cpp:103::close> closing fd[0x7], /tmp/mmkv/test2
[I] <MemoryFile.cpp:97::open> open fd[0x7], /tmp/mmkv/test2
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test2] with 103 actual size, file size 4096, InterProcess 0, meta info version:3
[I] <MMKV_IO.cpp:86::loadFromFile> loading [test2] with crc 2531236140 sequence 1 version 3
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test2] with 8 key-values
[I] <MMKV.cpp:1224::restoreOneFromDirectory> finish restore one mmkv[test2], ret: 1
[I] <MMKV.cpp:1205::restoreOneFromDirectory> restore one cached mmkv[test1] from [/tmp/mmkv_backup/test1] to [/tmp/mmkv/test1]
[I] <MemoryFile.cpp:97::open> open fd[0x9], /tmp/mmkv_backup/test1
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/test1 to fd[5] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x9], /tmp/mmkv_backup/test1
[I] <MemoryFile.cpp:97::open> open fd[0x9], /tmp/mmkv_backup/test1.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/test1.crc to fd[6] finish
[I] <MemoryFile.cpp:103::close> closing fd[0x9], /tmp/mmkv_backup/test1.crc
[I] <MMKV.cpp:290::clearMemoryCache> clearMemoryCache [test1]
[I] <MemoryFile.cpp:103::close> closing fd[0x5], /tmp/mmkv/test1
[I] <MemoryFile.cpp:97::open> open fd[0x5], /tmp/mmkv/test1
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test1] with 103 actual size, file size 4096, InterProcess 0, meta info version:3
[I] <MMKV_IO.cpp:86::loadFromFile> loading [test1] with crc 2531236140 sequence 1 version 3
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test1] with 8 key-values
[I] <MMKV.cpp:1224::restoreOneFromDirectory> finish restore one mmkv[test1], ret: 1
[I] <MemoryFile.cpp:97::open> open fd[0x9], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MMKV.cpp:1163::restoreOneFromDirectoryByFilePath> restore one mmkv[7c4333fc4397e1aaa06803afcd23f315] from [/tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81] to [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81]
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:97::open> open fd[0xb], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81 to fd[10] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xb], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:478::copyFileContent> copy content from /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81 to [/tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81
[I] <MemoryFile.cpp:97::open> open fd[0xa], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MemoryFile_Linux.cpp:113::copyFileContent> copy content from /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc to fd[9] finish
[I] <MemoryFile.cpp:103::close> closing fd[0xa], /tmp/mmkv_backup/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
[I] <MMKV.cpp:1174::restoreOneFromDirectoryByFilePath> finish restore one mmkv[7c4333fc4397e1aaa06803afcd23f315]
[I] <MemoryFile.cpp:103::close> closing fd[0x9], /tmp/mmkv/specialCharacter/4e566463fff4756aa8634a1f260d5f81.crc
-444

9. log打印处理

9.1 主要接口

@C
public struct MMKVHandler {
    public var mmkvLog: LogHandler = CFunc<(MMKVLogLevel, CString, Int32, CString, CString) -> Unit>(CPointer<Int8>())

    public var onMMKVCRCCheckFail: ErrorHandler = CFunc<(CString) -> MMKVRecoverStrategic>(CPointer<Int8>())

    public var onMMKVFileLengthError: ErrorHandler = CFunc<(CString) -> MMKVRecoverStrategic>(CPointer<Int8>())

    public var onMMKVContentChange: ContentChangeHandler = CFunc<(CString) -> Unit>(CPointer<Int8>())
}

public class MMKV {
    /*
    * 设置 log 等级
    *
    * 参数 - level log 等级
    */
    public static func setLogLevel(level: MMKVLogLevel): Unit

    /*
    * 注册用于 MMKV 日志处理程序
    *
    * 参数 - handler MMKV 的日志回调处理程序
    */
    public static func registerHandler(handler: MMKVHandler): Unit

    /*
    * 注销 MMKV 日志处理程序
    */
    public static func unregiserHandler(): Unit
}

9.2 示例

testLog.cj

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

main(): Int64 {
    var callbackHandler: MMKVHandler = MMKVHandler()
    callbackHandler.mmkvLog = { level, file, line, function, message =>
        println("r-${level} <${file}:${line}:${function}> ${message}")
    }

    callbackHandler.onMMKVCRCCheckFail = { mmapID =>
        return OnErrorRecover
    }

    callbackHandler.onMMKVFileLengthError = { mmapID =>
        return OnErrorRecover
    }

    callbackHandler.onMMKVContentChange = { mmapID =>
        println("MMKV other process has changed content of :  ${mmapID}")
    }

    MMKV.registerHandler(callbackHandler)
    MMKV.initializeMMKV("rootdir")
    var kv: MMKV = MMKV.mmkvWithID("test_handler")
    var ret = kv.set("registerHandler", "Hello, world!")
    if (ret == false) {
        return -1
    }

    MMKV.unregiserHandler()
    kv.clearMemoryCache()
    kv = MMKV.mmkvWithID("test_handler")
    ret = kv.set("unregiserHandler", "Hello, world!")
    if (ret == false) {
        return -1
    }

    return 0
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testLog.cj -o main

运行结果如下:

r-1 <MMKV.cpp:165:initialize> version v1.2.15, page size 4096, arch x86_64
r-1 <MMKV.cpp:208:initializeMMKV> root dir: rootdir
r-1 <MemoryFile.cpp:97:open> open fd[0x3], rootdir/test_handler
r-1 <MemoryFile.cpp:97:open> open fd[0x4], rootdir/test_handler.crc
r-1 <MMKV_IO.cpp:81:loadFromFile> loading [test_handler] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
r-1 <MMKV_IO.cpp:130:loadFromFile> loaded [test_handler] with 0 key-values
r-1 <MMKV_IO.cpp:451:writeActualSize> [test_handler] increase sequence to 1, crc 1285129681, actualSize 4
[I] <MMKV.cpp:290::clearMemoryCache> clearMemoryCache [test_handler]
[I] <MemoryFile.cpp:103::close> closing fd[0x3], rootdir/test_handler
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/test_handler
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test_handler] with 35 actual size, file size 4096, InterProcess 0, meta info version:3
[I] <MMKV_IO.cpp:86::loadFromFile> loading [test_handler] with crc 2997121558 sequence 1 version 3
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test_handler] with 1 key-values

10. 异常处理

10.1 主要接口

public class MMKVException <: Exception {
    public init() 

    public init(messages: String)

    public override func toString(): String
}

10.2 示例

testException.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

main(): Unit {
    try {
        var kv = MMKV.mmkvWithID("test")
    } catch (e: MMKVException) {
        println(e)
    }
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testException.cj -o main

运行结果如下:

MMKVException: You should Call MMKV.initializeMMKV() first.

11. 按key获取值并写到ptr内存

11.1 主要结构体

/* native memory 封装
 * 必须手动执行 destoryBuffer 销毁
 */
public struct NativeBuffer {
    public var pointer: CPointer<Unit> = CPointer<Unit>() // native memory 指针
    public var size: Int32 = 0 // native memory 大小
}

11.2 主要接口

public class MMKV {
    /*
    * 创建一个 native buffer,NativeBuffer 必须手动执行 destroyNativeBuffer,以避免内存泄漏。
    *
    * 参数 - size 申请内存大小
    *
    * 返回值 - NativeBuffer 创建的 native buffer
    */
    public func creatBuffer(size: UIntNative): NativeBuffer

    /*
    * 根据key获取的值写到内存中。如果内存不够直接返回 -1
    *
    * 参数 - key
    * 参数 - buffer creatBuffer 返回的 NativeBuffer,使用 creatBuffer 的返回值,使用其他值,将产生不可预知的问题。
    *
    * 返回值 - Int32 写入的大小
    */
    public func writeValueToBuffer(key: String, buffer: NativeBuffer): Int32

    /*
    * 销毁 native buffer。必须手动销毁 NativeBuffer 以避免内存泄漏。
    *
    * 参数 - buffer creatBuffer 返回的 NativeBuffer, 使用 creatBuffer 的返回值,使用其他值,将产生不可预知的问题。
    *
    * 返回值 - Unit
    */
    public func destoryBuffer(buffer: NativeBuffer): Unit
}

11.3 示例

testNativeBuffer.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

main() {
    MMKV.initializeMMKV("rootdir")
    var kv: MMKV = MMKV.mmkvWithID("test")
    var str = "hello cangjie writeValueToBuffer"

    kv.set("set0", str)
    println("key set0 value is: ${kv.getString("set0")}, size is: ${str.size}")
    var nbuff = kv.creatBuffer(200)

    var size = kv.writeValueToBuffer("set0", nbuff)
    var nbuffStr: String = CString(CPointer<UInt8>(nbuff.pointer)).toString()
    println("get from buffer is: ${nbuffStr}, size is: ${size}")
    kv.destoryBuffer(nbuff)
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testNativeBuffer.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/test
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/test.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [test] with 121 actual size, file size 4096, InterProcess 0, meta info version:3
[I] <MMKV_IO.cpp:86::loadFromFile> loading [test] with crc 664001669 sequence 1 version 3
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [test] with 1 key-values
key set0 value is: hello cangjie writeValueToBuffer, size is: 32
read from buffer is: hello cangjie writeValueToBuffer, size is: 32

12 . 加密key-value

12.1 主要接口

public class MMKV {
    /*
    * 获取加密秘钥
    *
    * 返回值 - String  返回加密秘钥
    */
    public func cryptKey(): String

    /*
    * 重置cryptKey加密密钥
    *
    * 参数 - cryptKey 新的加密密钥(不超过16字节)
    * 返回值 - Bool  返回是否重置成功
    */
    public func reKey(cryptKey: String): Bool

    /*
    * 检查是否被改了秘钥,如果被改了,那么重置为新的加密密钥
    *
    * 参数 - cryptKey 新的加密密钥(不超过16字节)
    * 返回值 - Unit
    */
    public func checkReSetCryptKey(cryptKey: String): Unit
}

12.2 示例

testCryptkey.cj

// EXEC: cjc %import-path %L %l %f
// EXEC: ./main

import kv4cj.*
import std.collection.*
import std.format.*
import std.core.*

public func checkReSetCryptKey_test00(kv: MMKV): Bool {
    kv.checkReSetCryptKey("") // nothing to do
    kv.checkReSetCryptKey("rekeyrekey") // "setting new aes key"
    var reKey_kvStr1: String = kv.cryptKey()
    var s0 = "rekeyrekey"
    if (reKey_kvStr1 != s0) {
        return false
    }
    kv.checkReSetCryptKey("rekeyrekey") // nothing to do
    return true
}

public func checkReSetCryptKey_test01(kv: MMKV): Bool {
    kv.checkReSetCryptKey("") // "reset aes key"

    var reKey_kvStr0: String = kv.cryptKey()
    var s0 = ""
    if (reKey_kvStr0 != s0) {
        return false
    }
    kv.checkReSetCryptKey("XXXxxxrekey")

    var reKey_kvStr1: String = kv.cryptKey()
    var s1 = "XXXxxxrekey"
    if (reKey_kvStr1 != s1) {
        return false
    }
    return true
}

main(): Int64 {
    var ret = 0
    MMKV.initializeMMKV("rootdir")

    var kv0: MMKV = MMKV.mmkvWithID("testcheckReSetCryptKey00")
    if (checkReSetCryptKey_test00(kv0) != true) {
        return -1
    }
    var kv1: MMKV = MMKV.mmkvWithID("tescheckReSetCryptKey01", 1, "checkKeyXXXX")
    if (checkReSetCryptKey_test01(kv1) != true) {
        return -1
    }
    return ret
}

编译运行:

cjc --import-path build -Lbuild/kv4cj -Llib -lcore -lkv4cj_mmkv -lmymmkv testCryptkey.cj -o main

运行结果如下:

[I] <MMKV.cpp:165::initialize> version v1.2.15, page size 4096, arch x86_64
[I] <MMKV.cpp:208::initializeMMKV> root dir: rootdir
[I] <MemoryFile.cpp:97::open> open fd[0x3], rootdir/testcheckReSetCryptKey00
[I] <MemoryFile.cpp:97::open> open fd[0x4], rootdir/testcheckReSetCryptKey00.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [testcheckReSetCryptKey00] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [testcheckReSetCryptKey00] with 0 key-values
[I] <MMKV.cpp:368::checkReSetCryptKey> setting new aes key
[I] <MemoryFile.cpp:97::open> open fd[0x5], rootdir/tescheckReSetCryptKey01
[I] <MemoryFile.cpp:97::open> open fd[0x6], rootdir/tescheckReSetCryptKey01.crc
[I] <MMKV_IO.cpp:81::loadFromFile> loading [tescheckReSetCryptKey01] with 0 actual size, file size 4096, InterProcess 0, meta info version:0
[I] <MMKV_IO.cpp:130::loadFromFile> loaded [tescheckReSetCryptKey01] with 0 key-values
[I] <MMKV.cpp:360::checkReSetCryptKey> reset aes key
[I] <MMKV.cpp:368::checkReSetCryptKey> setting new aes key