FileQueryEngine.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.IO;
  5. using Y.FileQueryEngine.UsnOperation;
  6. namespace Y.FileQueryEngine.QueryEngine
  7. {
  8. public class FileQueryEngine
  9. {
  10. /// <summary>
  11. /// When its values is 1407374883553285(0x5000000000005L), it means this file/folder is under drive root
  12. /// </summary>
  13. public const UInt64 ROOT_FILE_REFERENCE_NUMBER = 0x5000000000005L;
  14. protected static readonly string excludeFolders = string.Join("|",
  15. new string[]
  16. {
  17. "$RECYCLE.BIN",
  18. "System Volume Information",
  19. "$AttrDef",
  20. "$BadClus",
  21. "$BitMap",
  22. "$Boot",
  23. "$LogFile",
  24. "$Mft",
  25. "$MftMirr",
  26. "$Secure",
  27. "$TxfLog",
  28. "$UpCase",
  29. "$Volume",
  30. "$Extend"
  31. }).ToUpper();
  32. /// <summary>
  33. /// 获取所有NTFS文件系统的固定磁盘
  34. /// </summary>
  35. /// <returns></returns>
  36. public static IEnumerable<DriveInfo> GetFixedNtfsDrives()
  37. {
  38. return DriveInfo.GetDrives()
  39. .Where(d => d.DriveType == DriveType.Fixed && d.DriveFormat.ToUpper() == "NTFS");
  40. }
  41. /// <summary>
  42. /// 获取所有NTFS文件系统的磁盘
  43. /// </summary>
  44. /// <returns></returns>
  45. public static IEnumerable<DriveInfo> GetReadyNtfsDrives()
  46. {
  47. return DriveInfo.GetDrives()
  48. .Where(d => d.IsReady && d.DriveFormat.ToUpper() == "NTFS");
  49. }
  50. /// <summary>
  51. /// 查询磁盘的所有文件
  52. /// </summary>
  53. /// <param name="drive"></param>
  54. /// <returns></returns>
  55. public static List<UsnEntry> GetAllFiles(DriveInfo drive)
  56. {
  57. var usnOperator = new UsnOperator(drive);
  58. return usnOperator.GetEntries().Where(e => !excludeFolders.Contains(e.FileName.ToUpper())).ToList();
  59. }
  60. public static bool FileIsExist(string drive, long usn)
  61. {
  62. var d = DriveInfo.GetDrives().FirstOrDefault(x => x.Name == drive);
  63. if (d != null)
  64. {
  65. var usnOperator = new UsnOperator(d);
  66. return usnOperator.UsnIsExist(usn);
  67. }
  68. return false;
  69. }
  70. /// <summary>
  71. /// 查询磁盘的所有文件
  72. /// </summary>
  73. /// <param name="drive"></param>
  74. /// <returns></returns>
  75. public static List<FileAndDirectoryEntry> GetAllFileEntrys(DriveInfo drive)
  76. {
  77. List<FileAndDirectoryEntry> result = new List<FileAndDirectoryEntry>();
  78. var usnOperator = new UsnOperator(drive);
  79. var usnEntries = usnOperator.GetEntries().Where(e => !excludeFolders.Contains(e.FileName.ToUpper()));
  80. var folders = usnEntries.Where(e => e.IsFolder).ToArray();
  81. List<FrnFilePath> paths = GetFolderPath(folders, drive);
  82. var range = usnEntries.Join(
  83. paths,
  84. usn => usn.ParentFileReferenceNumber,
  85. path => path.FileReferenceNumber,
  86. (usn, path) => new FileAndDirectoryEntry(usn, path.Path));
  87. result.AddRange(range);
  88. return result;
  89. }
  90. private static List<FrnFilePath> GetFolderPath(UsnEntry[] folders, DriveInfo drive)
  91. {
  92. Dictionary<UInt64, FrnFilePath> pathDic = new Dictionary<ulong, FrnFilePath>();
  93. pathDic.Add(ROOT_FILE_REFERENCE_NUMBER,
  94. new FrnFilePath(ROOT_FILE_REFERENCE_NUMBER, null, string.Empty, drive.Name.TrimEnd('\\')));
  95. foreach (var folder in folders)
  96. {
  97. pathDic.Add(folder.FileReferenceNumber,
  98. new FrnFilePath(folder.FileReferenceNumber, folder.ParentFileReferenceNumber, folder.FileName));
  99. }
  100. Stack<UInt64> treeWalkStack = new Stack<ulong>();
  101. foreach (var key in pathDic.Keys)
  102. {
  103. treeWalkStack.Clear();
  104. FrnFilePath currentValue = pathDic[key];
  105. if (string.IsNullOrWhiteSpace(currentValue.Path)
  106. && currentValue.ParentFileReferenceNumber.HasValue
  107. && pathDic.ContainsKey(currentValue.ParentFileReferenceNumber.Value))
  108. {
  109. FrnFilePath parentValue = pathDic[currentValue.ParentFileReferenceNumber.Value];
  110. while (string.IsNullOrWhiteSpace(parentValue.Path)
  111. && parentValue.ParentFileReferenceNumber.HasValue
  112. && pathDic.ContainsKey(parentValue.ParentFileReferenceNumber.Value))
  113. {
  114. currentValue = parentValue;
  115. if (currentValue.ParentFileReferenceNumber.HasValue
  116. && pathDic.ContainsKey(currentValue.ParentFileReferenceNumber.Value))
  117. {
  118. treeWalkStack.Push(key);
  119. parentValue = pathDic[currentValue.ParentFileReferenceNumber.Value];
  120. }
  121. else
  122. {
  123. parentValue = null;
  124. break;
  125. }
  126. }
  127. if (parentValue != null)
  128. {
  129. currentValue.Path = BuildPath(currentValue, parentValue);
  130. while (treeWalkStack.Count() > 0)
  131. {
  132. UInt64 walkedKey = treeWalkStack.Pop();
  133. FrnFilePath walkedNode = pathDic[walkedKey];
  134. FrnFilePath parentNode = pathDic[walkedNode.ParentFileReferenceNumber.Value];
  135. walkedNode.Path = BuildPath(walkedNode, parentNode);
  136. }
  137. }
  138. }
  139. }
  140. var result = pathDic.Values.Where(p => !string.IsNullOrWhiteSpace(p.Path) && p.Path.StartsWith(drive.Name)).ToList();
  141. return result;
  142. }
  143. private static string BuildPath(FrnFilePath currentNode, FrnFilePath parentNode)
  144. {
  145. return string.Concat(new string[] { parentNode.Path, "\\", currentNode.FileName });
  146. }
  147. }
  148. }