FileUtil.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. using XGame.Framework;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using UnityEngine;
  7. namespace XGame.Editor.Asset
  8. {
  9. public static class FileUtil
  10. {
  11. ///// <summary>
  12. ///// 收集指定路径下的指定后缀的文件
  13. ///// </summary>
  14. ///// <param name="rootPath"></param>
  15. ///// <param name="patterns"></param>
  16. ///// <param name="isFindSelected"></param>
  17. ///// <returns></returns>
  18. //public static List<string> CollectFiles(string rootPath, string[] patterns, bool isFindSelected)
  19. //{
  20. // List<string> allFiles = new List<string>();
  21. // if (!Directory.Exists(rootPath))
  22. // return allFiles;
  23. // foreach (var pattern in patterns)
  24. // {
  25. // var files = Directory.GetFiles(rootPath, pattern, SearchOption.AllDirectories);
  26. // foreach (var file in files)
  27. // allFiles.Add(file.Replace("\\", "/"));
  28. // }
  29. // // 只对选择物体打包
  30. // if (isFindSelected)
  31. // {
  32. // // 返回一个交集 就是判断当前选择是否满足条件
  33. // return allFiles.Intersect(Selection.objects.Select(AssetDatabase.GetAssetPath)).ToList();
  34. // }
  35. // else
  36. // {
  37. // return allFiles;
  38. // }
  39. //}
  40. /// <summary>
  41. /// 贴图文件后缀
  42. /// </summary>
  43. public static readonly string[] texturePatterns = { ".png", ".jpg", ".tga", ".psd" };
  44. private static readonly string textureExts = ".png.jpg.tga.psd";
  45. /// <summary>
  46. /// 图集配置文件后缀
  47. /// </summary>
  48. public static readonly string spriteatlasPattern = ".spriteatlas";
  49. /// <summary>
  50. /// 文件是否是Texture
  51. /// </summary>
  52. /// <param name="filePath"></param>
  53. /// <returns></returns>
  54. public static bool IsTextureFile(string filePath)
  55. {
  56. var ext = Path.GetExtension(filePath);
  57. return string.IsNullOrEmpty(ext) == false && textureExts.Contains(ext, StringComparison.OrdinalIgnoreCase);
  58. }
  59. /// <summary>
  60. /// 是否是SpriteAtlas文件
  61. /// </summary>
  62. /// <param name="filePath"></param>
  63. /// <returns></returns>
  64. public static bool IsSpriteAtlas(string filePath)
  65. {
  66. return filePath.EndsWith(spriteatlasPattern, StringComparison.OrdinalIgnoreCase);
  67. }
  68. /// <summary>
  69. /// 查找指定文件夹下的指定类型的文件
  70. /// </summary>
  71. /// <param name="path"></param>
  72. /// <param name="patterns">文件后缀名</param>
  73. /// <param name="option"></param>
  74. /// <returns></returns>
  75. public static string[] FindFiles(string path, string[] patterns, SearchOption option = SearchOption.AllDirectories)
  76. {
  77. if (!Directory.Exists(path) || patterns == null)
  78. {
  79. return new string[0];
  80. }
  81. var files = Directory.GetFiles(path, "*.*", option).Where(file =>
  82. {
  83. foreach (var pattern in patterns)
  84. {
  85. if (file.EndsWith(pattern))
  86. {
  87. return true;
  88. }
  89. }
  90. return false;
  91. }).ToArray();
  92. for (var i = 0; i < files.Length; i++)
  93. {
  94. files[i] = files[i].Replace("\\", "/");
  95. }
  96. return files;
  97. }
  98. /// <summary>
  99. /// 查找指定文件夹下的指定类型的文件
  100. /// </summary>
  101. /// <param name="path"></param>
  102. /// <param name="pattern">必须使用"*."开头</param>
  103. /// <param name="option"></param>
  104. /// <returns></returns>
  105. public static string[] FindFiles(string path, string pattern, SearchOption option = SearchOption.AllDirectories)
  106. {
  107. if (!Directory.Exists(path) || string.IsNullOrEmpty(pattern))
  108. { //文件夹不存在或后缀名为空
  109. return new string[0];
  110. }
  111. //必须使用"*."开头
  112. if (pattern.StartsWith("."))
  113. {
  114. pattern = $"*{pattern}";
  115. }
  116. var files = Directory.GetFiles(path, pattern, option);
  117. for (var i = 0; i < files.Length; i++)
  118. {
  119. files[i] = files[i].Replace("\\", "/");
  120. }
  121. return files;
  122. }
  123. /// <summary>
  124. /// 查找指定路径下的所有文件
  125. /// </summary>
  126. /// <param name="path"></param>
  127. /// <returns></returns>
  128. public static string[] FindFiles(string path)
  129. {
  130. List<string> lst = new List<string>();
  131. FindFiles(path, (files) =>
  132. {
  133. lst.AddRange(files);
  134. });
  135. return lst.ToArray();
  136. }
  137. /// <summary>
  138. /// 查找指定路径下的所有文件,按照所在文件夹批次返回结果
  139. /// path为全路径,则返回的也是全路径
  140. /// path为AssetPath,则返回的也是AssetPath
  141. /// </summary>
  142. /// <param name="path"></param>
  143. /// <param name="action"></param>
  144. public static void FindFiles(string path, System.Action<string[]> action)
  145. {
  146. var lst = new List<string>();
  147. var files = Directory.GetFiles(path).Where((file) => !IsFileIgnore(file)).ToArray();
  148. if (files.Length > 0 && action != null)
  149. {
  150. for (var i = 0; i < files.Length; i++)
  151. {
  152. files[i] = files[i].Replace("\\", "/");
  153. }
  154. action.Invoke(files);
  155. }
  156. var dirs = Directory.GetDirectories(path);
  157. foreach (var dir in dirs)
  158. {
  159. FindFiles(dir, action);
  160. }
  161. }
  162. /// <summary>
  163. /// 忽略的文件格式
  164. /// </summary>
  165. //static readonly string[] ignoreFiles = { ".meta", ".gitkeep", ".spriteatlas", ".DS_Store", ".cs", ".pdb" };
  166. static readonly string ignoreFiles = "*.meta*.gitkeep*.spriteatlas*.DS_Store*.cs*.pdb";
  167. public static bool IsFileIgnore(string path)
  168. {
  169. //if (!File.Exists(path))
  170. //{
  171. // return true;
  172. //}
  173. var ext = Path.GetExtension(path);
  174. return string.IsNullOrEmpty(ext) == false && ignoreFiles.Contains(ext, StringComparison.OrdinalIgnoreCase);
  175. }
  176. /// <summary>
  177. /// 获取文件所在文件夹的名字
  178. /// </summary>
  179. /// <param name="path"></param>
  180. /// <param name="fullName"></param>
  181. /// <returns></returns>
  182. public static string GetDirectoryName(string path, bool fullName)
  183. {
  184. path = Path.GetDirectoryName(path)?.Replace("\\", "/");
  185. if (!fullName)
  186. {
  187. int idx = path?.LastIndexOf("/", StringComparison.Ordinal) ?? -1;
  188. if (idx != -1)
  189. {
  190. path = path?.Substring(idx + 1);
  191. }
  192. }
  193. return path;
  194. }
  195. /// <summary>
  196. /// 全路径转相对路径
  197. /// (Assets/...)
  198. /// </summary>
  199. /// <param name="fullPath"></param>
  200. /// <returns></returns>
  201. public static string ToRelativePath(string fullPath)
  202. {
  203. int index = fullPath.IndexOf(PathDefine.AssetsRelative, StringComparison.Ordinal);
  204. if (index == 0)
  205. {
  206. return fullPath;
  207. }
  208. else if (index < 0)
  209. { //没有 "Assets/" 或者在开头
  210. index = fullPath.IndexOf(PathDefine.PackageRelative, StringComparison.Ordinal); //Packages里的资源以Packages/开头,全名为"Packages/{包名}/..."
  211. if (index == 0)
  212. {//Packages下资源的相对路径
  213. return fullPath;
  214. }
  215. else if (index < 0)
  216. {
  217. var packageRoot = PathDefine.PackageReality;
  218. index = fullPath.IndexOf(packageRoot, StringComparison.Ordinal);
  219. if (index >= 0)
  220. {
  221. //Packages下资源的全路径
  222. var tempPath = fullPath.Substring(index + packageRoot.Length);
  223. var index_0 = tempPath.IndexOf('@');
  224. var index_1 = tempPath.IndexOf('/');
  225. if (index_1 - index_0 > 0 && index_0 >= 0)
  226. {//裁剪版本信息
  227. var version = tempPath.Substring(index_0, index_1 - index_0);
  228. tempPath = $"{PathDefine.PackageRelative}{tempPath.Replace(version, "")}";
  229. }
  230. return tempPath;
  231. }
  232. return fullPath;
  233. }
  234. }
  235. return fullPath.Substring(index);
  236. }
  237. /// <summary>
  238. /// 判断字符串是否是数字
  239. /// </summary>
  240. /// <param name="message"></param>
  241. /// <param name="result"></param>
  242. /// <returns></returns>
  243. public static bool IsNumberic(string message, out int result)
  244. {
  245. System.Text.RegularExpressions.Regex rex =
  246. new System.Text.RegularExpressions.Regex(@"^\d+$");
  247. result = -1;
  248. if (rex.IsMatch(message))
  249. {
  250. result = int.Parse(message);
  251. return true;
  252. }
  253. else
  254. return false;
  255. }
  256. /// <summary>
  257. /// 检测指定路径是否是包含平台信息
  258. /// result 返回1表是当前平台,返回-1表示包含平台信息但不是当前平台,返回0表示没有包含平台信息
  259. /// </summary>
  260. /// <param name="path"></param>
  261. /// <param name="platformNames"></param>
  262. /// <returns></returns>
  263. public static int VerifyPlatformPath(string path, string[] platformNames = null)
  264. {
  265. if (platformNames == null)
  266. {
  267. platformNames = Enum.GetNames(typeof(PlatformType));
  268. }
  269. var current = PlatformUtil.ActivePlatform.ToString();
  270. var projectPath = Environment.CurrentDirectory.Replace("\\", "/");
  271. var startIndex = path.StartsWith(projectPath) ? projectPath.Length : 0;
  272. foreach (var name in platformNames)
  273. {
  274. var platformIndex = path.IndexOf(name, startIndex);
  275. if (platformIndex >= 0)
  276. {
  277. if (name.Equals(current))
  278. {
  279. return 1;
  280. }
  281. return -1;
  282. }
  283. }
  284. return 0;
  285. }
  286. /// <summary>
  287. /// 可加载资源路径
  288. /// </summary>
  289. /// <param name="includeResources"></param>
  290. /// <returns></returns>
  291. public static string[] GetProductAssetsRoots(bool includeResources = false)
  292. {
  293. ICollection<string> roots = new HashSet<string>();
  294. if (Directory.Exists(PathDefine.ResAddressableRelative))
  295. {
  296. roots.Add(PathDefine.ResAddressableRelative);
  297. }
  298. if (includeResources && Directory.Exists(PathDefine.ResourcesRelative))
  299. {
  300. roots.Add(PathDefine.ResourcesRelative);
  301. }
  302. GetDirectories(PathDefine.I18nAssetsRelative, PathDefine.ResAddressableName, SearchOption.AllDirectories, ref roots);
  303. return roots.ToArray();
  304. }
  305. public static string[] GetI18nAssetsRoots()
  306. {
  307. ICollection<string> directories = new HashSet<string>();
  308. GetDirectories(PathDefine.I18nAssetsRelative, PathDefine.ResAddressableName, SearchOption.AllDirectories, ref directories);
  309. return directories.ToArray();
  310. }
  311. /// <summary>
  312. /// 获取图集文件夹
  313. /// 文件夹名字:Atlas
  314. /// </summary>
  315. /// <returns></returns>
  316. public static string[] GetAtlasRoots()
  317. {
  318. const string atlasDir = "Atlas";
  319. ICollection<string> directories = new HashSet<string>();
  320. GetDirectories(PathDefine.ResAddressableRelative, atlasDir, SearchOption.AllDirectories, ref directories);
  321. GetDirectories(PathDefine.ResStaticRelative, atlasDir, SearchOption.AllDirectories, ref directories);
  322. GetDirectories(PathDefine.I18nAssetsRelative, atlasDir, SearchOption.AllDirectories, ref directories);
  323. return directories.ToArray();
  324. }
  325. private static void GetDirectories(string path, string searchPattern, SearchOption searchOption, ref ICollection<string> directories)
  326. {
  327. if (Directory.Exists(path))
  328. {
  329. var result = Directory.GetDirectories(path, searchPattern, searchOption);
  330. foreach (var directory in result)
  331. {
  332. directories.Add(directory.Replace("\\", "/"));
  333. }
  334. }
  335. }
  336. public static bool HasChinese(string str)
  337. {
  338. return System.Text.RegularExpressions.Regex.IsMatch(str, @"[\u4e00-\u9fa5]");
  339. }
  340. //[UnityEditor.MenuItem("Tools/Test/GenManifestBundleId")]
  341. //public static void GenManifestBundleId()
  342. //{
  343. // var str = $"ProductAssetManifest.asset_AssetBundleManifest.asset_AssetReferenceManifest.asset";
  344. // var bundleId = Crc32.GetCrc32(str);
  345. // Debug.Log($"GenManifestBundleId:{bundleId}");
  346. //}
  347. }
  348. }