Skip to content

windows_tutorial

guoling edited this page Apr 3, 2026 · 17 revisions

MMKV for Windows

MMKV is an efficient, small, easy-to-use mobile key-value storage framework used in the WeChat application. It's currently available on Android, iOS/macOS, Windows, POSIX and HarmonyOS NEXT.

Tutorial

You can use MMKV as you go. All changes are saved immediately, no save, no sync calls are needed.

Configuration

  • Setup MMKV on App startup, say in your main(), add these codes:

    #include <MMKV/MMKV.h>
    
    int main() {
        std::wstring rootDir = getYourAppDocumentDir();
        MMKV::initializeMMKV(rootDir);
        //...
    }

CRUD Operations

  • MMKV has a global instance, that can be used directly:

    auto mmkv = MMKV::defaultMMKV();
    
    mmkv->set(true, "bool");
    std::cout << "bool = " << mmkv->getBool("bool") << std::endl;
    
    mmkv->set(1024, "int32");
    std::cout << "int32 = " << mmkv->getInt32("int32") << std::endl;
    
    mmkv->set(numeric_limits<uint32_t>::max(), "uint32");
    std::cout << "uint32 = " << mmkv->getUInt32("uint32") << std::endl;
    
    mmkv->set(numeric_limits<int64_t>::min(), "int64");
    std::cout << "int64 = " << mmkv->getInt64("int64") << std::endl;
    
    mmkv->set(numeric_limits<uint64_t>::max(), "uint64");
    std::cout << "uint64 = " << mmkv->getUInt64("uint64") << std::endl;
    
    mmkv->set(3.14f, "float");
    std::cout << "float = " << mmkv->getFloat("float") << std::endl;
    
    mmkv->set(numeric_limits<double>::max(), "double");
    std::cout << "double = " << mmkv->getDouble("double") << std::endl;
    
    mmkv->set("Hello, MMKV for Windows", "string");
    std::string result;
    if (mmkv->getString("string", result)) {
       std::cout << "string = " << result << std::endl;
    }

    As you can see, MMKV is quite easy to use.

  • Deleting & Querying:

    auto mmkv = MMKV::defaultMMKV();
    
    mmkv->removeValueForKey("bool");
    std::cout << "bool = " << mmkv->getBool("bool") << std::endl;
    
    mmkv->removeValuesForKeys({"int32", "int64"});
    std::cout << "allKeys: ";
    for (auto &key : mmkv->allKeys()) {
        std::cout << key << ", ";
    }
    std::cout << std::endl;
          
    bool hasBool = mmkv->containsKey("bool");
  • If different modules/logics need isolated storage, you can also create your own MMKV instance separately:

    auto mmkv = MMKV::mmkvWithID("MyID");
    mmkv->set(true, "bool");
  • If multi-process accessing is needed, you can set MMKV_MULTI_PROCESS on MMKV initialization:

    auto mmkv = MMKV::mmkvWithID("InterProcessKV", MMKV_MULTI_PROCESS);
    mmkv->set(true, "bool");

Supported Types

  • Primitive Types:

    • bool, int32, int64, uint32, uint64, float, double
  • Classes & Collections:

    • std::string, std::vector<std::string>, mmkv::MMBuffer

Logs

  • By default, MMKV prints log to stdout, which is not convenient for diagnosing online issues. You can set up MMKV log redirecting on App startup. Implement callback function with type mmkv::LogHandler(), add some code like these:

    void MyLogHandler(MMKVLogLevel level, const char *file, int line, const char *function, const string &message) {
        auto desc = [level] {
            switch (level) {
                case MMKVLogDebug:
                    return "D";
                case MMKVLogInfo:
                    return "I";
                case MMKVLogWarning:
                    return "W";
                case MMKVLogError:
                    return "E";
                default:
                    return "N";
            }
        }();
        printf("[%s] <%s:%d::%s> %s\n", desc, file, line, function, message.c_str());
    }
    int main() {
        std::wstring rootDir = getYourAppDocumentDir();
        MMKV::initializeMMKV(rootDir, MMKVLogInfo, MyLogHandler);
        //...
    }

    As for a logging tool, we recommend using xlog, which also comes from the WeChat team.

  • You can turn off MMKV's logging once and for all (which we strongly discourage).
    You should never turn MMKV's log off unless you have very strong evidence that it makes your App slow.

    MMKV::initializeMMKV(rootDir, MMKVLogNone);

Encryption

  • By default MMKV stores all key-values in plain text on file. Should you worry about information leaking, you can choose to encrypt MMKV. MMKV supports both AES CFB-128 and AES CFB-256 encryption. By default AES-128 is used (keys are truncated to 16 bytes). To use AES-256, you must explicitly pass aes256 = true.

    std::string cryptKey = "My-Encrypt-Key";
    auto mmkv = MMKV::mmkvWithID("MyID", MMKV_SINGLE_PROCESS, &cryptKey);
  • You can change the encryption key later as you like. You can also change an existing MMKV instance from encrypted to unencrypted, or vice versa.

    // an unencrypted MMKV instance
    auto kv = MMKV::mmkvWithID("testAES_reKey");
    
    std::string key1 = "Key_seq_1";
    // change from unencrypted to encrypted with AES-128 key length
    kv->reKey(key1);
    
    std::string key2 = "Key_Seq_Very_Looooooooong";
    // change encryption key with AES-256 key length
    kv->reKey(key2, true);
    
    // change from encrypted to unencrypted
    kv->reKey(std::string());

Recover from data corruption

  • By default, MMKV discards all data when there's a CRC check fail, or file length is not correct. You can set up error handling by implementing mmkv::MMKVHandler and registering it:

    class MyHandler : public mmkv::MMKVHandler {
    public:
        MMKVRecoverStrategic onMMKVCRCCheckFail(const std::string &mmapID) override {
            return OnErrorRecover;
        }
    
        MMKVRecoverStrategic onMMKVFileLengthError(const std::string &mmapID) override {
            return OnErrorRecover;
        }
    };
    
    // register on startup
    MyHandler handler;
    MMKV::registerHandler(&handler);

    You can also pass the handler during initialization:

    MMKV::initializeMMKV(rootDir, MMKVLogInfo, &handler);

Content change notification

  • You can receive notifications when content changes by another process:

    class MyHandler : public mmkv::MMKVHandler {
    public:
        void onContentChangedByOuterProcess(const std::string &mmapID) override {
            // handle content change
        }
    
        void onMMKVContentLoadSuccessfully(const std::string &mmapID) override {
            // content loaded
        }
    };

Backup & Restore

  • You can use MMKV's backup & restore API to backup your data to somewhere else, and restore them later.

    std::string rootDir = "/tmp/mmkv_backup";
    auto ret = MMKV::backupOneToDirectory(mmapID, rootDir);
    // backup all instances
    auto count = MMKV::backupAllToDirectory(rootDir);
    
    // restore one instance
    ret = MMKV::restoreOneFromDirectory(mmapID, rootDir);
    // restore all instances
    count = MMKV::restoreAllFromDirectory(rootDir);

Auto Expiration

  • Starting from v1.3.0, you can upgrade MMKV to auto key expiration. Note that this is a breaking change. Once upgraded to auto key expiration, the file is not valid for any older version of MMKV (<= v1.2.16) to operate correctly.

  • Global Expiration. The most simple way to do it is to turn on auto key expiration for all keys in the whole file.

    // expire in a day
    mmkv->enableAutoKeyExpire(24 * 60 * 60);

    Or, if you prefer, you can enable auto key expiration without setting a global expiration duration. In this case, each key is not expired by default.

    // enable auto key expiration without global duration
    mmkv->enableAutoKeyExpire(MMKV::ExpireNever); // MMKV::ExpireNever = 0
  • Individual Expiration. You can set a special expiration duration for a key, regardless of whether the file has a global duration or not. Note that you have to enable auto key expiration first.

    // enable auto key expiration with an hour duration
    mmkv->enableAutoKeyExpire(60 * 60);
    
    // set a key with the file's global expiration duration, aka 60 * 60
    mmkv->set("some value", "key_1");
    
    // set a special key that expires in two hours
    mmkv->set("some value", "key_2", 2 * 60 * 60);
    
    // set a special key that never expires
    mmkv->set("some value", "key_3", MMKV::ExpireNever);

    Or, if you prefer, you can enable auto key expiration without setting a global expiration duration. In this case, each key is not expired by default.

    // enable auto key expiration without global duration
    mmkv->enableAutoKeyExpire(MMKV::ExpireNever); // MMKV::ExpireNever = 0
    
    // set a key that never expires
    mmkv->set("some value", "key_1");
    
    // set a special key that expires in an hour
    mmkv->set("some value", "key_2", 60 * 60);
  • The expire duration is counted in seconds. You can use any other duration you prefer. For example, expiration in a week is 7 * 24 * 60 * 60.

  • You can turn off auto key expiration:

    mmkv->disableAutoKeyExpire();

    Note: Once disabled, the file format stays upgraded. Old MMKV versions (<= v1.2.16) still cannot operate on it.

  • You can query non-expired keys:

    auto nonExpiredCount = mmkv->count(true); // true = filter expired
    auto nonExpiredKeys = mmkv->allKeys(true); // true = filter expired

Instance Utility

  • MMKV provides several utility methods for inspecting and managing instances:

    auto mmkv = MMKV::defaultMMKV();
    
    // size info
    auto totalSize = mmkv->totalSize();
    auto actualSize = mmkv->actualSize();
    auto keyCount = mmkv->count();
    
    // import from another instance
    auto other = MMKV::mmkvWithID("other");
    mmkv->importFrom(other);
    
    // manually sync to file
    mmkv->sync(MMKV_SYNC);
    mmkv->sync(MMKV_ASYNC);
    
    // reclaim disk space after heavy deletions
    mmkv->trim();
    
    // clear all with keeping file space (for reuse)
    mmkv->clearAll(true);

File Management

  • You can check, validate, and remove MMKV storage files:

    // check if an MMKV file exists
    bool exists = MMKV::checkExist("MyID");
    
    // validate file integrity
    bool valid = MMKV::isFileValid("MyID");
    
    // remove MMKV storage files
    MMKV::removeStorage("MyID");

Read-Only Mode

  • Starting from v2.4.0, you can open an MMKV instance in read-only mode. Any write operation will be silently ignored.

    auto mmkv = MMKV::mmkvWithID("MyID", MMKV_READ_ONLY);
    // or combine with multi-process
    auto mmkv = MMKV::mmkvWithID("MyID", MMKV_MULTI_PROCESS | MMKV_READ_ONLY);

Compare Before Set

  • Starting from v2.4.0, you can turn on enableCompareBeforeSet() to reduce unnecessary write operations.

    mmkv->enableCompareBeforeSet();

    Note: enableCompareBeforeSet() is NOT compatible with encryption or auto key expiration.

  • You can turn it off later:

    mmkv->disableCompareBeforeSet();

MMKVConfig

  • Starting from v2.4.0, MMKV provides an all-in-one config struct MMKVConfig for convenient instance creation. It's an aggregate struct with default values — create one and set the fields you need.

    MMKVConfig config;
    config.cryptKey = &myKey;  // const std::string*
    config.mode = MMKV_MULTI_PROCESS;
    auto kv = MMKV::mmkvWithID("MyID", config);
    
    // or use the default MMKV with config
    MMKVConfig defaultConfig;
    auto defaultKV = MMKV::defaultMMKV(defaultConfig);

    Available fields (all have sensible defaults):

    Field Type Default Description
    mode MMKVMode MMKV_SINGLE_PROCESS Single or multi-process mode
    cryptKey const std::string* nullptr Encryption key
    aes256 bool false Use AES-256 key length
    rootPath const MMKVPath_t* nullptr Custom root directory
    expectedCapacity size_t 0 Initial file size hint
    enableKeyExpire std::optional<bool> nullopt Enable/disable auto key expiration
    expiredInSeconds uint32_t 0 Default expiration duration in seconds
    enableCompareBeforeSet bool false Compare value before writing
    recover std::optional<MMKVRecoverStrategic> nullopt Per-instance recovery strategy
    itemSizeLimit uint32_t 0 Max size per key-value pair (0 = unlimited)

NameSpace

Starting from v2.1.0, MMKV supports the NameSpace feature. It’s primarily designed to solve these problems:

  1. Using in other modules/3rd lib/SDK without initialization Traditionally, MMKV requires initialization before use, and it will cause problems in multiple libs because one can’t be sure if MMKV has been initialized, nor can be sure of the root directory of MMKV. With NameSpace, a lib can use MMKV without initialization, and of course without configuring global root directory.
  2. Make customizing root directory easy Using NameSpace you can customize the root directory of a group of MMKV instances easily.
  std::string rootDir = "/tmp/mmkv_namespace";
  auto ns = MMKV::nameSpace(rootDir);
  auto kv = ns.mmkvWithID(mmapID);
  • Backup & Restore within a NameSpace:

    // backup/restore within a namespace
    ns.backupOneToDirectory(mmapID, dstPath);
    ns.restoreOneFromDirectory(mmapID, dstPath);
    ns.backupAllToDirectory(dstPath);
    ns.restoreAllFromDirectory(dstPath);
  • Utility methods on NameSpace:

    bool valid = ns.isFileValid(mmapID);
    bool exists = ns.checkExist(mmapID);
    ns.removeStorage(mmapID);

Next

Clone this wiki locally