local Storage = {} local private = {} local Infrast = require("Infrast/Infrast") private.OpenedStorageHandleList = {} -- 这个是 storageHandle 到 identity 的映射 private.StorageTable = {} -- 这个是 storageHandle 到 table 的映射 local StoragePathName = "Storage" local PathStr = "%s/%s" --[[ 这个类是用于存贮、获取本地数据,比如本地设置等 使用方法: 1、首先创建 local storageHandle = Storage.OpenOrCreate(identity) identity 为字符串标识用于记录是那个模块的功能 2、之后可以通过 SetValue、RemoveValue、GetValue 来获取、修改、移除本地的KV数据,immediatelySave 这个参数为缺省参数,用来表示 是否实时存储到本地, 因为存储有一定消耗,根据具体的功能模块选择是否实时储存 3、对KV的操作运行时会有缓存列表,优先会从缓存列表中读、写,并不会实时从文件中读写,所以需要有对文件的操作 Delete —— 移除移除/清空storageHandle标识的本地文件 Save —— 保存storageHandle标识的本地文件,即将缓存写入到本地文件中 DeleteAll —— 移除全部本地文件,谨慎使用,尽量不要在自己的功能模块中调用该方法,可能会把其他模块存储的内容也清理掉 例子: local a = Storage.OpenOrCreate("Team") -- 创建"Team"模块的存储对象a Storage.Save(a) -- 将本地缓存的 a的数据保存到本地文件中 print(Storage.GetValue(a, "abc", 123)) -- 从对象a对应的文件中获取 k为"abc"的值,如果没有k为"abc"则返回123 Storage.SetValue(a, "abc", 10086, true) -- 将k为"abc",值为10086保存到对象a对应的文件中 Storage.RemoveValue(a, "abc") -- 从对象a对应的文件中移除 k为"abc"的值 Storage.Delete(a) -- 清空移除 对象a对应的文件 Storage.DeleteAll() -- 将Storage文件夹中 所有本地储存的文件全部清理移除掉 ]]-- -- Start Storage相关 -- 创建 function Storage.OpenOrCreate(identity) -- 获取handle for index, v in ipairs(private.OpenedStorageHandleList) do if v == identity then return index end end -- 第一次获取 需要需要创建 handle local storageHandle = #private.OpenedStorageHandleList + 1 private.OpenedStorageHandleList[storageHandle] = identity -- 创建 Table ,从文件中 读取数据,如果文件不存在不会创建文件,设置为空表 local suc = pcall(private.InitTable, storageHandle) if not suc then logging.error(LTAG.ERROR, "[Storage]初始化StorageTable失败:identity = ", identity) end return storageHandle end -- 移除/清空 function Storage.Delete(storageHandle) LuaExt.FileDelete(private.GetFilePath(storageHandle)) private.OpenedStorageHandleList[storageHandle] = nil private.StorageTable[storageHandle] = nil end -- 保存 function Storage.Save(storageHandle) local storageTb = private.StorageTable[storageHandle] if storageTb then local path = private.GetFilePath(storageHandle) local createSuc = pcall(private.CreatePathAndFile, path) if not createSuc then logging.error(LTAG.ERROR, "[Storage]创建路径、文件失败:identity = ", private.OpenedStorageHandleList[storageHandle]) return end local encodeSuc, content = pcall(Infrast.EncodeToBytes, storageTb) if not encodeSuc then logging.error(LTAG.ERROR, "[Storage]二进制序列化失败:identity = ", private.OpenedStorageHandleList[storageHandle], ", table = ", storageTb) return end LuaExt.FileWriteBytes(path, false, content) else logging.error(LTAG.ERROR, "[Storage.Save]当前 storageHandle 不存在,请先调用 CreateStorage:identity = ", private.OpenedStorageHandleList[storageHandle]) end end -- 移除/清空全部 function Storage.DeleteAll() LuaExt.DirectoryDelete(StoragePathName, true) private.OpenedStorageHandleList = {} private.StorageTable = {} end -- End Storage相关 End -- Start KV相关(需要依赖Storage) Start -- 新增/修改 function Storage.SetValue(storageHandle, key, value, immediatelySave) local storageTb = private.StorageTable[storageHandle] if storageTb then storageTb[key] = value if immediatelySave then Storage.Save(storageHandle) end else logging.error(LTAG.ERROR, "[Storage.SetValue]storageHandle 不存在,请先调用 CreateStorage:identity = ", private.OpenedStorageHandleList[storageHandle]) end end -- 移除 function Storage.RemoveValue(storageHandle, key, immediatelySave) local storageTb = private.StorageTable[storageHandle] if storageTb then if storageTb[key] then storageTb[key] = nil if immediatelySave then Storage.Save(storageHandle) end end else logging.error(LTAG.ERROR, "[Storage.RemoveValue]storageHandle 不存在,请先调用 CreateStorage:identity = ", private.OpenedStorageHandleList[storageHandle]) end end -- 移除/清空 function Storage.RemoveAllValue(storageHandle, immediatelySave) private.StorageTable[storageHandle] = {} if immediatelySave then Storage.Save(storageHandle) end end -- 查询 function Storage.GetValue(storageHandle, key, defValue) local storageTb = private.StorageTable[storageHandle] local value = nil if storageTb then value = storageTb[key] else logging.error(LTAG.ERROR, "[Storage.GetValue]storageHandle 不存在,请先调用 CreateStorage:identity = ", private.OpenedStorageHandleList[storageHandle]) end if value == nil then return defValue else return value end end -- End KV相关 End ---------- Start 内部方法(主要用于辅助实现) Start ---------- function private.InitTable(storageHandle) local path = private.GetFilePath(storageHandle) local suc, content if LuaExt.FileExists(path) then content = LuaExt.FileReadBytes(path) suc, content = pcall(Infrast.DecodeFromBytes, content) if not suc then logging.error(LTAG.ERROR, "[Storage]二进制解码失败:identity", private.OpenedStorageHandleList[storageHandle]) end end if type(content) ~= "table" then private.StorageTable[storageHandle] = {} else private.StorageTable[storageHandle] = content end end function private.CreatePathAndFile(path) LuaExt.DirectoryCreate(StoragePathName) -- 防止路径没有创建出来,内部会有是否已经创建的判断 if not LuaExt.FileExists(path) then LuaExt.FileWriteText(path, "") end end function private.GetFilePath(storageHandle) return string.format(PathStr, StoragePathName, private.OpenedStorageHandleList[storageHandle]) end ---------- End 内部方法(主要用于辅助实现) End ---------- return Storage