using BetterGenshinImpact.Core.Script.Utils; using System; using System.IO; using System.Threading.Tasks; using OpenCvSharp; using System.Linq; using BetterGenshinImpact.GameTask.Common; using Microsoft.Extensions.Logging; namespace BetterGenshinImpact.Core.Script.Dependence; public class LimitedFile(string rootPath) { /// /// 读取指定文件夹内所有文件和文件夹的路径(非递归方式)。 /// /// 文件夹路径(相对于根目录) /// 文件夹内所有文件和文件夹的路径数组 public string[] ReadPathSync(string folderPath) { try { // 对传入的文件夹路径进行标准化 string normalizedFolderPath = NormalizePath(folderPath); // 确保目录存在 if (!Directory.Exists(normalizedFolderPath)) { Directory.CreateDirectory(normalizedFolderPath); } // 获取指定文件夹下的所有文件(非递归) string[] files = Directory.GetFiles(normalizedFolderPath, "*", SearchOption.TopDirectoryOnly); // 获取指定文件夹下的所有子文件夹(非递归) string[] directories = Directory.GetDirectories(normalizedFolderPath, "*", SearchOption.TopDirectoryOnly); // 合并文件和文件夹路径 string[] combined = files.Concat(directories).ToArray(); // 将绝对路径转换为相对于 rootPath 的相对路径 return combined.Select(path => Path.GetRelativePath(rootPath, path)).ToArray(); } catch (Exception ex) { // 记录异常并返回空数组 TaskControl.Logger.LogError("ReadPathSync 异常: {Message}", ex.Message); return Array.Empty(); } } /// /// 判断指定路径是否为文件夹。 /// /// 文件或文件夹路径(相对于根目录)。 /// 如果该路径是文件夹则返回 true,否则返回 false。 public bool IsFolder(string path) { try { // 对传入的路径进行标准化处理 string normalizedPath = NormalizePath(path); // 使用 Directory.Exists 判断标准化路径是否为文件夹 return Directory.Exists(normalizedPath); } catch (Exception ex) { // 记录异常并返回 false TaskControl.Logger.LogError("IsFolder 异常: {Message}", ex.Message); return false; } } /// /// Normalize and validate a path. /// private string NormalizePath(string path) { return ScriptUtils.NormalizePath(rootPath, path); } /// /// Read all text from a file. /// /// File path. /// Text read from file. public string ReadTextSync(string path) { try { path = NormalizePath(path); return File.ReadAllText(path); } catch (Exception ex) { // 记录异常并返回空字符串 TaskControl.Logger.LogError("ReadTextSync 异常: {Message}", ex.Message); return string.Empty; } } /// /// Read all text from a file. /// /// File path. /// Text read from file. public async Task ReadText(string path) { try { path = NormalizePath(path); var ret = await File.ReadAllTextAsync(path); return ret; } catch (Exception ex) { // 记录异常并返回空字符串 TaskControl.Logger.LogError("ReadText 异常: {Message}", ex.Message); return string.Empty; } } /// /// Read all text from a file. /// /// File path. /// Callback function. /// Text read from file. public async Task ReadText(string path, dynamic callbackFunc) { try { path = NormalizePath(path); var ret = await File.ReadAllTextAsync(path); callbackFunc(null, ret); return ret; } catch (Exception ex) { callbackFunc(ex.ToString(), null); return string.Empty; } } /// /// 读取Mat图片 /// /// /// public Mat ReadImageMatSync(string path) { try { path = NormalizePath(path); using var stream = File.OpenRead(path); var mat = Mat.FromStream(stream, ImreadModes.Color); return mat; } catch (Exception ex) { // 记录异常并返回空的Mat TaskControl.Logger.LogError("ReadImageMatSync 异常: {Message}", ex.Message); return new Mat(); } } /// /// 读取图像文件为Mat对象,并调整到指定尺寸 /// /// 图像文件路径 /// 调整后的宽度 /// 调整后的高度 /// 插值算法,默认为双线性插值(1) /// 调整尺寸后的Mat图像对象 /// /// 支持的插值算法: /// /// 最近邻插值 (0) /// 双线性插值 (1) - 默认 /// 双三次插值 (2) /// 像素区域关系重采样 (3) /// Lanczos插值 (4) /// 精确双线性插值 (5) /// /// public Mat ReadImageMatWithResizeSync(string path, double width, double height, int interpolation = 1) { try { if (width <= 0 || height <= 0) { throw new Exception("ReadImageMatWithResizeSync: 宽度和高度必须为正数"); } if (interpolation is < 0 or > 5) { throw new Exception($"ReadImageMatWithResizeSync: 不支持的插值算法 {interpolation}"); } path = NormalizePath(path); using var stream = File.OpenRead(path); using var mat = Mat.FromStream(stream, ImreadModes.Color); var rsz = new Mat(); Cv2.Resize(mat, rsz, new Size(width, height), 0, 0, (InterpolationFlags)interpolation); return rsz; } catch (Exception ex) { // 记录异常并返回空的Mat TaskControl.Logger.LogError("ReadImageMatWithResizeSync 异常: {Message}", ex.Message); return new Mat(); } } /// /// 允许的文件扩展名白名单 /// private readonly string[] _allowedExtensions = [".txt", ".json", ".log", ".csv", ".xml", ".html", ".css", ".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".webp"]; /// /// 最大允许的文件大小(字节) /// private const long MaxFileSize = 999 * 1024 * 1024; // 999 MB /// /// 验证路径和内容是否合法,并确保目录存在 /// /// 文件路径 /// 要写入的内容,如果为null则只验证路径 /// 是否合法 private bool IsValid(string path, string? content = null) { try { // 验证文件扩展名 string extension = Path.GetExtension(path).ToLower(); if (!Array.Exists(_allowedExtensions, ext => ext == extension)) { return false; } // 确保目录存在 var normalizedPath = NormalizePath(path); string? directoryPath = Path.GetDirectoryName(normalizedPath); if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } // 如果提供了内容,验证内容是否合法 if (content != null) { // 检查文件大小 if (content.Length > MaxFileSize) { return false; } } return true; } catch (Exception ex) { // 记录异常并返回 false TaskControl.Logger.LogError("IsValid 异常: {Message}", ex.Message); return false; } } /// /// 同步写入文本到文件 /// /// 文件路径 /// 要写入的内容 /// 是否追加到文件末尾,默认为false(覆盖) /// 是否写入成功 public bool WriteTextSync(string path, string content, bool append = false) { try { path = NormalizePath(path); if (!IsValid(path, content)) { return false; } if (append && File.Exists(path)) { File.AppendAllText(path, content); } else { File.WriteAllText(path, content); } return true; } catch { return false; } } /// /// 异步写入文本到文件 /// /// 文件路径 /// 要写入的内容 /// 是否追加到文件末尾,默认为false(覆盖) /// 是否写入成功 public async Task WriteText(string path, string content, bool append = false) { try { path = NormalizePath(path); if (!IsValid(path, content)) { return false; } if (append && File.Exists(path)) { await File.AppendAllTextAsync(path, content); } else { await File.WriteAllTextAsync(path, content); } return true; } catch { return false; } } /// /// 异步写入文本到文件(带回调) /// /// 文件路径 /// 要写入的内容 /// 回调函数 /// 是否追加到文件末尾,默认为false(覆盖) /// 是否写入成功 public async Task WriteText(string path, string content, dynamic callbackFunc, bool append = false) { try { path = NormalizePath(path); if (!IsValid(path, content)) { callbackFunc("路径不合法或文件内容不合法", null); return false; } if (append && File.Exists(path)) { await File.AppendAllTextAsync(path, content); } else { await File.WriteAllTextAsync(path, content); } callbackFunc(null, true); return true; } catch (Exception ex) { callbackFunc(ex.ToString(), null); return false; } } /// /// 同步写入图片到文件(默认PNG格式) /// /// 文件路径 /// OpenCV Mat对象 /// 是否写入成功 public bool WriteImageSync(string path, Mat mat) { try { // 自动追加.png后缀 path = EnsureImageExtension(path); path = NormalizePath(path); if (!IsValidImagePath(path)) { return false; } // 确保目录存在 string? directoryPath = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } // 使用OpenCV保存图片(默认PNG格式) Cv2.ImWrite(path, mat); return true; } catch (Exception ex) { // 记录异常并返回 false TaskControl.Logger.LogError("WriteImageSync 异常: {Message}", ex.Message); return false; } } /// /// 确保图片路径有正确的扩展名,如果没有则自动追加.png /// /// 文件路径 /// 带有正确扩展名的路径 private string EnsureImageExtension(string path) { string extension = Path.GetExtension(path).ToLower(); string[] imageExtensions = [".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".webp"]; // 如果已经有图片扩展名,直接返回 if (Array.Exists(imageExtensions, ext => ext == extension)) { return path; } // 如果没有扩展名,自动追加.png return path + ".png"; } /// /// 验证图片路径是否合法 /// /// 文件路径 /// 是否合法 private bool IsValidImagePath(string path) { // 验证文件扩展名 string extension = Path.GetExtension(path).ToLower(); string[] imageExtensions = [".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".webp"]; if (!Array.Exists(imageExtensions, ext => ext == extension)) { return false; } return true; } }