110 lines
4.5 KiB
C#
110 lines
4.5 KiB
C#
|
|
using System.IO;
|
|||
|
|
using System.Text;
|
|||
|
|
|
|||
|
|
namespace SHH.CameraDashboard
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 本地文件存储服务
|
|||
|
|
/// 职责:
|
|||
|
|
/// 1. 提供通用的、异步的对象序列化和反序列化功能。
|
|||
|
|
/// 2. 将对象保存为 UTF-8 编码的 JSON 文件。
|
|||
|
|
/// 3. 从 JSON 文件中读取并反序列化为对象。
|
|||
|
|
/// 4. 处理文件不存在、内容为空或格式错误等常见异常情况。
|
|||
|
|
/// </summary>
|
|||
|
|
public static class LocalStorageService
|
|||
|
|
{
|
|||
|
|
#region --- 保存方法 ---
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 将指定对象异步保存到文件。
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T">要保存的对象的类型。</typeparam>
|
|||
|
|
/// <param name="filePath">目标文件的完整路径。</param>
|
|||
|
|
/// <param name="data">要保存的对象实例。</param>
|
|||
|
|
/// <exception cref="Exception">当保存过程中发生任何错误时抛出。</exception>
|
|||
|
|
public static async Task SaveAsync<T>(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 --- 加载方法 ---
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 从文件异步加载并反序列化为指定类型的对象。
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T">目标对象的类型。必须是引用类型且具有公共无参数构造函数。</typeparam>
|
|||
|
|
/// <param name="filePath">源文件的完整路径。</param>
|
|||
|
|
/// <returns>
|
|||
|
|
/// 成功时返回反序列化后的对象。
|
|||
|
|
/// 如果文件不存在、内容为空、格式错误或发生任何异常,将返回一个新创建的默认对象实例。
|
|||
|
|
/// </returns>
|
|||
|
|
public static async Task<T> LoadAsync<T>(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<T>(json);
|
|||
|
|
|
|||
|
|
// 5. 如果反序列化结果为 null (例如,JSON 内容为 "null" 或格式不匹配),
|
|||
|
|
// 则返回一个新的默认对象作为兜底。
|
|||
|
|
return result ?? new T();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
// 记录错误到调试输出
|
|||
|
|
System.Diagnostics.Debug.WriteLine($"读取文件失败 [{filePath}]: {ex.Message}");
|
|||
|
|
// 发生任何异常(如文件被占用、权限问题等),都返回一个新的默认对象,
|
|||
|
|
// 以确保程序能够继续运行而不会崩溃。
|
|||
|
|
return new T();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
}
|