using System.IO;
using System.Text;
namespace SHH.CameraDashboard
{
///
/// 本地文件存储服务
/// 职责:
/// 1. 提供通用的、异步的对象序列化和反序列化功能。
/// 2. 将对象保存为 UTF-8 编码的 JSON 文件。
/// 3. 从 JSON 文件中读取并反序列化为对象。
/// 4. 处理文件不存在、内容为空或格式错误等常见异常情况。
///
public static class LocalStorageService
{
#region --- 保存方法 ---
///
/// 将指定对象异步保存到文件。
///
/// 要保存的对象的类型。
/// 目标文件的完整路径。
/// 要保存的对象实例。
/// 当保存过程中发生任何错误时抛出。
public static async Task SaveAsync(string filePath, T data)
{
try
{
// 1. 确保文件所在的目录存在,如果不存在则创建
var directoryPath = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
// 2. 使用 JsonHelper 将对象序列化为 JSON 字符串
string json = JsonHelper.Serialize(data);
// 3. 使用 StreamWriter 异步将 JSON 字符串写入文件
// - `false` 表示覆盖现有文件。
// - `Encoding.UTF8` 确保文件编码正确,特别是处理中文字符时。
using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
await writer.WriteAsync(json);
}
}
catch (Exception ex)
{
// 记录错误到调试输出
System.Diagnostics.Debug.WriteLine($"保存文件失败 [{filePath}]: {ex.Message}");
// 重新抛出异常,因为保存失败通常是一个需要上层处理的严重问题(例如,提示用户)
throw;
}
}
#endregion
#region --- 加载方法 ---
///
/// 从文件异步加载并反序列化为指定类型的对象。
///
/// 目标对象的类型。必须是引用类型且具有公共无参数构造函数。
/// 源文件的完整路径。
///
/// 成功时返回反序列化后的对象。
/// 如果文件不存在、内容为空、格式错误或发生任何异常,将返回一个新创建的默认对象实例。
///
public static async Task LoadAsync(string filePath) where T : class, new()
{
// 1. 如果文件不存在,直接返回一个新的默认对象
if (!File.Exists(filePath))
{
return new T();
}
try
{
// 2. 使用 StreamReader 异步读取文件全部内容
using (var reader = new StreamReader(filePath, Encoding.UTF8))
{
string json = await reader.ReadToEndAsync();
// 3. 如果文件内容为空或只包含空白字符,返回一个新的默认对象
if (string.IsNullOrWhiteSpace(json))
{
return new T();
}
// 4. 使用 JsonHelper 尝试反序列化 JSON 字符串
var result = JsonHelper.Deserialize(json);
// 5. 如果反序列化结果为 null (例如,JSON 内容为 "null" 或格式不匹配),
// 则返回一个新的默认对象作为兜底。
return result ?? new T();
}
}
catch (Exception ex)
{
// 记录错误到调试输出
System.Diagnostics.Debug.WriteLine($"读取文件失败 [{filePath}]: {ex.Message}");
// 发生任何异常(如文件被占用、权限问题等),都返回一个新的默认对象,
// 以确保程序能够继续运行而不会崩溃。
return new T();
}
}
#endregion
}
}