using System.Text; using GFramework.Core.Abstractions.storage; using GFramework.Game.Abstractions.serializer; namespace GFramework.Game.storage; /// /// 基于文件系统的存储实现,实现了IStorage接口 /// public sealed class FileStorage : IStorage { private readonly string _extension; private readonly string _rootPath; private readonly ISerializer _serializer; /// /// 初始化FileStorage实例 /// /// 存储根目录路径 /// 序列化器实例 /// 存储文件的扩展名 public FileStorage(string rootPath, ISerializer serializer, string extension = ".dat") { _rootPath = rootPath; _serializer = serializer; _extension = extension; Directory.CreateDirectory(_rootPath); } #region Delete /// /// 删除指定键的存储项 /// /// 存储键 public void Delete(string key) { var path = ToPath(key); if (File.Exists(path)) File.Delete(path); } #endregion #region Helpers /// /// 将存储键转换为文件路径 /// /// 存储键 /// 对应的文件路径 private string ToPath(string key) { // 防止非法路径 key = Path.GetInvalidFileNameChars().Aggregate(key, (current, c) => current.Replace(c, '_')); return Path.Combine(_rootPath, $"{key}{_extension}"); } #endregion #region Exists /// /// 检查指定键的存储项是否存在 /// /// 存储键 /// 存在返回true,否则返回false public bool Exists(string key) => File.Exists(ToPath(key)); /// /// 异步检查指定键的存储项是否存在 /// /// 存储键 /// 存在返回true,否则返回false public Task ExistsAsync(string key) => Task.FromResult(Exists(key)); #endregion #region Read /// /// 读取指定键的存储项 /// /// 要反序列化的类型 /// 存储键 /// 反序列化后的对象 /// 当指定键不存在时抛出 public T Read(string key) { var path = ToPath(key); if (!File.Exists(path)) throw new FileNotFoundException($"Storage key not found: {key}", path); var content = File.ReadAllText(path, Encoding.UTF8); return _serializer.Deserialize(content); } /// /// 读取指定键的存储项,如果不存在则返回默认值 /// /// 要反序列化的类型 /// 存储键 /// 默认值 /// 存在则返回反序列化后的对象,否则返回默认值 public T Read(string key, T defaultValue) { var path = ToPath(key); if (!File.Exists(path)) return defaultValue; var content = File.ReadAllText(path, Encoding.UTF8); return _serializer.Deserialize(content); } /// /// 异步读取指定键的存储项 /// /// 要反序列化的类型 /// 存储键 /// 反序列化后的对象 /// 当指定键不存在时抛出 public async Task ReadAsync(string key) { var path = ToPath(key); if (!File.Exists(path)) throw new FileNotFoundException($"Storage key not found: {key}", path); var content = await File.ReadAllTextAsync(path, Encoding.UTF8); return _serializer.Deserialize(content); } #endregion #region Write /// /// 写入指定键的存储项 /// /// 要序列化的类型 /// 存储键 /// 要存储的值 public void Write(string key, T value) { var path = ToPath(key); var content = _serializer.Serialize(value); File.WriteAllText(path, content, Encoding.UTF8); } /// /// 异步写入指定键的存储项 /// /// 要序列化的类型 /// 存储键 /// 要存储的值 public async Task WriteAsync(string key, T value) { var path = ToPath(key); var content = _serializer.Serialize(value); await File.WriteAllTextAsync(path, content, Encoding.UTF8); } #endregion }