using XGame.Framework; using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; namespace XGame.Editor.Asset { public static class FileUtil { ///// ///// 收集指定路径下的指定后缀的文件 ///// ///// ///// ///// ///// //public static List CollectFiles(string rootPath, string[] patterns, bool isFindSelected) //{ // List allFiles = new List(); // if (!Directory.Exists(rootPath)) // return allFiles; // foreach (var pattern in patterns) // { // var files = Directory.GetFiles(rootPath, pattern, SearchOption.AllDirectories); // foreach (var file in files) // allFiles.Add(file.Replace("\\", "/")); // } // // 只对选择物体打包 // if (isFindSelected) // { // // 返回一个交集 就是判断当前选择是否满足条件 // return allFiles.Intersect(Selection.objects.Select(AssetDatabase.GetAssetPath)).ToList(); // } // else // { // return allFiles; // } //} /// /// 贴图文件后缀 /// public static readonly string[] texturePatterns = { ".png", ".jpg", ".tga", ".psd" }; private static readonly string textureExts = ".png.jpg.tga.psd"; /// /// 图集配置文件后缀 /// public static readonly string spriteatlasPattern = ".spriteatlas"; /// /// 文件是否是Texture /// /// /// public static bool IsTextureFile(string filePath) { var ext = Path.GetExtension(filePath); return string.IsNullOrEmpty(ext) == false && textureExts.Contains(ext, StringComparison.OrdinalIgnoreCase); } /// /// 是否是SpriteAtlas文件 /// /// /// public static bool IsSpriteAtlas(string filePath) { return filePath.EndsWith(spriteatlasPattern, StringComparison.OrdinalIgnoreCase); } /// /// 查找指定文件夹下的指定类型的文件 /// /// /// 文件后缀名 /// /// public static string[] FindFiles(string path, string[] patterns, SearchOption option = SearchOption.AllDirectories) { if (!Directory.Exists(path) || patterns == null) { return new string[0]; } var files = Directory.GetFiles(path, "*.*", option).Where(file => { foreach (var pattern in patterns) { if (file.EndsWith(pattern)) { return true; } } return false; }).ToArray(); for (var i = 0; i < files.Length; i++) { files[i] = files[i].Replace("\\", "/"); } return files; } /// /// 查找指定文件夹下的指定类型的文件 /// /// /// 必须使用"*."开头 /// /// public static string[] FindFiles(string path, string pattern, SearchOption option = SearchOption.AllDirectories) { if (!Directory.Exists(path) || string.IsNullOrEmpty(pattern)) { //文件夹不存在或后缀名为空 return new string[0]; } //必须使用"*."开头 if (pattern.StartsWith(".")) { pattern = $"*{pattern}"; } var files = Directory.GetFiles(path, pattern, option); for (var i = 0; i < files.Length; i++) { files[i] = files[i].Replace("\\", "/"); } return files; } /// /// 查找指定路径下的所有文件 /// /// /// public static string[] FindFiles(string path) { List lst = new List(); FindFiles(path, (files) => { lst.AddRange(files); }); return lst.ToArray(); } /// /// 查找指定路径下的所有文件,按照所在文件夹批次返回结果 /// path为全路径,则返回的也是全路径 /// path为AssetPath,则返回的也是AssetPath /// /// /// public static void FindFiles(string path, System.Action action) { var lst = new List(); var files = Directory.GetFiles(path).Where((file) => !IsFileIgnore(file)).ToArray(); if (files.Length > 0 && action != null) { for (var i = 0; i < files.Length; i++) { files[i] = files[i].Replace("\\", "/"); } action.Invoke(files); } var dirs = Directory.GetDirectories(path); foreach (var dir in dirs) { FindFiles(dir, action); } } /// /// 忽略的文件格式 /// //static readonly string[] ignoreFiles = { ".meta", ".gitkeep", ".spriteatlas", ".DS_Store", ".cs", ".pdb" }; static readonly string ignoreFiles = "*.meta*.gitkeep*.spriteatlas*.DS_Store*.cs*.pdb"; public static bool IsFileIgnore(string path) { //if (!File.Exists(path)) //{ // return true; //} var ext = Path.GetExtension(path); return string.IsNullOrEmpty(ext) == false && ignoreFiles.Contains(ext, StringComparison.OrdinalIgnoreCase); } /// /// 获取文件所在文件夹的名字 /// /// /// /// public static string GetDirectoryName(string path, bool fullName) { path = Path.GetDirectoryName(path)?.Replace("\\", "/"); if (!fullName) { int idx = path?.LastIndexOf("/", StringComparison.Ordinal) ?? -1; if (idx != -1) { path = path?.Substring(idx + 1); } } return path; } /// /// 全路径转相对路径 /// (Assets/...) /// /// /// public static string ToRelativePath(string fullPath) { int index = fullPath.IndexOf(PathDefine.AssetsRelative, StringComparison.Ordinal); if (index == 0) { return fullPath; } else if (index < 0) { //没有 "Assets/" 或者在开头 index = fullPath.IndexOf(PathDefine.PackageRelative, StringComparison.Ordinal); //Packages里的资源以Packages/开头,全名为"Packages/{包名}/..." if (index == 0) {//Packages下资源的相对路径 return fullPath; } else if (index < 0) { var packageRoot = PathDefine.PackageReality; index = fullPath.IndexOf(packageRoot, StringComparison.Ordinal); if (index >= 0) { //Packages下资源的全路径 var tempPath = fullPath.Substring(index + packageRoot.Length); var index_0 = tempPath.IndexOf('@'); var index_1 = tempPath.IndexOf('/'); if (index_1 - index_0 > 0 && index_0 >= 0) {//裁剪版本信息 var version = tempPath.Substring(index_0, index_1 - index_0); tempPath = $"{PathDefine.PackageRelative}{tempPath.Replace(version, "")}"; } return tempPath; } return fullPath; } } return fullPath.Substring(index); } /// /// 判断字符串是否是数字 /// /// /// /// public static bool IsNumberic(string message, out int result) { System.Text.RegularExpressions.Regex rex = new System.Text.RegularExpressions.Regex(@"^\d+$"); result = -1; if (rex.IsMatch(message)) { result = int.Parse(message); return true; } else return false; } /// /// 检测指定路径是否是包含平台信息 /// result 返回1表是当前平台,返回-1表示包含平台信息但不是当前平台,返回0表示没有包含平台信息 /// /// /// /// public static int VerifyPlatformPath(string path, string[] platformNames = null) { if (platformNames == null) { platformNames = Enum.GetNames(typeof(PlatformType)); } var current = PlatformUtil.ActivePlatform.ToString(); var projectPath = Environment.CurrentDirectory.Replace("\\", "/"); var startIndex = path.StartsWith(projectPath) ? projectPath.Length : 0; foreach (var name in platformNames) { var platformIndex = path.IndexOf(name, startIndex); if (platformIndex >= 0) { if (name.Equals(current)) { return 1; } return -1; } } return 0; } /// /// 可加载资源路径 /// /// /// public static string[] GetProductAssetsRoots(bool includeResources = false) { ICollection roots = new HashSet(); if (Directory.Exists(PathDefine.ResAddressableRelative)) { roots.Add(PathDefine.ResAddressableRelative); } if (includeResources && Directory.Exists(PathDefine.ResourcesRelative)) { roots.Add(PathDefine.ResourcesRelative); } GetDirectories(PathDefine.I18nAssetsRelative, PathDefine.ResAddressableName, SearchOption.AllDirectories, ref roots); return roots.ToArray(); } public static string[] GetI18nAssetsRoots() { ICollection directories = new HashSet(); GetDirectories(PathDefine.I18nAssetsRelative, PathDefine.ResAddressableName, SearchOption.AllDirectories, ref directories); return directories.ToArray(); } /// /// 获取图集文件夹 /// 文件夹名字:Atlas /// /// public static string[] GetAtlasRoots() { const string atlasDir = "Atlas"; ICollection directories = new HashSet(); GetDirectories(PathDefine.ResAddressableRelative, atlasDir, SearchOption.AllDirectories, ref directories); GetDirectories(PathDefine.ResStaticRelative, atlasDir, SearchOption.AllDirectories, ref directories); GetDirectories(PathDefine.I18nAssetsRelative, atlasDir, SearchOption.AllDirectories, ref directories); return directories.ToArray(); } private static void GetDirectories(string path, string searchPattern, SearchOption searchOption, ref ICollection directories) { if (Directory.Exists(path)) { var result = Directory.GetDirectories(path, searchPattern, searchOption); foreach (var directory in result) { directories.Add(directory.Replace("\\", "/")); } } } public static bool HasChinese(string str) { return System.Text.RegularExpressions.Regex.IsMatch(str, @"[\u4e00-\u9fa5]"); } //[UnityEditor.MenuItem("Tools/Test/GenManifestBundleId")] //public static void GenManifestBundleId() //{ // var str = $"ProductAssetManifest.asset_AssetBundleManifest.asset_AssetReferenceManifest.asset"; // var bundleId = Crc32.GetCrc32(str); // Debug.Log($"GenManifestBundleId:{bundleId}"); //} } }