PathUtils.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. using MeloongCore.Extensions;
  2. using System.IO;
  3. using System.Runtime.InteropServices;
  4. using System.Text;
  5. namespace MeloongCore;
  6. public static class PathUtils {
  7. /// <summary>
  8. /// 若路径较长,则尽量将其转换为短路径。
  9. /// 若输入的是文件夹路径,不保证其结尾是否有 \ 。
  10. /// </summary>
  11. public static string Shorten(string fullName, bool keepFileName = false) {
  12. if (string.IsNullOrEmpty(fullName) || fullName.Length <= 200) return fullName;
  13. fullName = fullName.Replace('/', '\\');
  14. // 保留文件名
  15. string pathToKeep = "";
  16. string pathToShorten = fullName;
  17. if (fullName.EndsWithF(".jar", true)) keepFileName = true; // jar 文件的文件名需要保留原样,否则会导致 Forge 1.20.1 无法通过文件名识别模块名
  18. if (keepFileName && File.Exists(fullName)) {
  19. pathToKeep = Path.GetFileName(fullName);
  20. pathToShorten = Path.GetDirectoryName(fullName);
  21. }
  22. // 逐级向上寻找已存在的文件夹,将不存在的部分挪到 suffix,不再缩短
  23. while (!Directory.Exists(pathToShorten) && !File.Exists(pathToShorten)) { // 如果路径不存在
  24. string parentPath = Path.GetDirectoryName(pathToShorten);
  25. if (string.IsNullOrEmpty(parentPath) || parentPath == pathToShorten) return fullName; // 已经到达根目录,全都不存在,直接返回
  26. pathToKeep = Path.Combine(Path.GetFileName(pathToShorten), pathToKeep);
  27. pathToShorten = parentPath;
  28. }
  29. if (pathToShorten.Length <= 10) return fullName;
  30. // 缩短路径
  31. var buffer = new StringBuilder(260);
  32. if (GetShortPathNameW(pathToShorten, buffer, buffer.Capacity) == 0) return fullName;
  33. return Path.Combine(buffer.ToString(), pathToKeep);
  34. }
  35. [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
  36. private static extern int GetShortPathNameW(string lpszLongPath, StringBuilder lpszShortPath, int cchBuffer);
  37. }