已开启
迷宫游戏-湖北工业大学-刘咏琪-徐承志 #151
阔阔阔落创建于 2025年6月28日
迷宫游戏-湖北工业大学-刘咏琪-徐承志 #151
已开启
共 2 个文件变更+1034-0
| @@ -0,0 +1,516 @@ | |||
| 1 | +import os | ||
| 2 | +import time | ||
| 3 | +import random | ||
| 4 | +from typing import Optional, List, Tuple | ||
| 5 | + | ||
| 6 | +class TreeNode: | ||
| 7 | + """二叉搜索树节点,表示文件系统中的一个文件或目录""" | ||
| 8 | + | ||
| 9 | + def __init__(self, file_path: str, is_directory: bool = False): | ||
| 10 | + self.file_path = file_path | ||
| 11 | + self.file_name = os.path.basename(file_path) | ||
| 12 | + self.is_directory = is_directory | ||
| 13 | + self.size = self._calculate_size() | ||
| 14 | + self.created_time = time.time() | ||
| 15 | + self.left: Optional[TreeNode] = None | ||
| 16 | + self.right: Optional[TreeNode] = None | ||
| 17 | + | ||
| 18 | + def _calculate_size(self) -> int: | ||
| 19 | + """计算文件或目录的大小""" | ||
| 20 | + if not os.path.exists(self.file_path): | ||
| 21 | + return 0 | ||
| 22 | + | ||
| 23 | + if not self.is_directory: | ||
| 24 | + return os.path.getsize(self.file_path) | ||
| 25 | + | ||
| 26 | + # 递归计算目录大小 | ||
| 27 | + total_size = 0 | ||
| 28 | + for dirpath, _, filenames in os.walk(self.file_path): | ||
| 29 | + for f in filenames: | ||
| 30 | + fp = os.path.join(dirpath, f) | ||
| 31 | + try: | ||
| 32 | + total_size += os.path.getsize(fp) | ||
| 33 | + except OSError: | ||
| 34 | + pass | ||
| 35 | + return total_size | ||
| 36 | + | ||
| 37 | + def __str__(self) -> str: | ||
| 38 | + """节点的字符串表示""" | ||
| 39 | + node_type = "DIR" if self.is_directory else "FILE" | ||
| 40 | + size_str = self._format_size(self.size) | ||
| 41 | + created_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.created_time)) | ||
| 42 | + return f"{node_type} | {self.file_name} | {size_str} | {created_str}" | ||
| 43 | + | ||
| 44 | + def _format_size(self, size_bytes: int) -> str: | ||
| 45 | + """格式化文件大小为人类可读的形式""" | ||
| 46 | + if size_bytes < 1024: | ||
| 47 | + return f"{size_bytes} B" | ||
| 48 | + elif size_bytes < 1024 * 1024: | ||
| 49 | + return f"{size_bytes / 1024:.2f} KB" | ||
| 50 | + elif size_bytes < 1024 * 1024 * 1024: | ||
| 51 | + return f"{size_bytes / (1024 * 1024):.2f} MB" | ||
| 52 | + else: | ||
| 53 | + return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB" | ||
| 54 | + | ||
| 55 | + | ||
| 56 | +class BinarySearchTree: | ||
| 57 | + """二叉搜索树实现,用于文件系统索引管理""" | ||
| 58 | + | ||
| 59 | + def __init__(self): | ||
| 60 | + self.root: Optional[TreeNode] = None | ||
| 61 | + self.node_count = 0 | ||
| 62 | + | ||
| 63 | + def insert(self, file_path: str, is_directory: bool = False) -> bool: | ||
| 64 | + """插入文件或目录到二叉搜索树""" | ||
| 65 | + if not os.path.exists(file_path): | ||
| 66 | + print(f"错误: 文件或目录不存在 - {file_path}") | ||
| 67 | + return False | ||
| 68 | + | ||
| 69 | + new_node = TreeNode(file_path, is_directory) | ||
| 70 | + | ||
| 71 | + if self.root is None: | ||
| 72 | + self.root = new_node | ||
| 73 | + self.node_count += 1 | ||
| 74 | + return True | ||
| 75 | + | ||
| 76 | + # 递归插入 | ||
| 77 | + def _insert_recursive(node: TreeNode, new_node: TreeNode) -> TreeNode: | ||
| 78 | + if new_node.file_name < node.file_name: | ||
| 79 | + if node.left is None: | ||
| 80 | + node.left = new_node | ||
| 81 | + else: | ||
| 82 | + node.left = _insert_recursive(node.left, new_node) | ||
| 83 | + else: | ||
| 84 | + if node.right is None: | ||
| 85 | + node.right = new_node | ||
| 86 | + else: | ||
| 87 | + node.right = _insert_recursive(node.right, new_node) | ||
| 88 | + return node | ||
| 89 | + | ||
| 90 | + _insert_recursive(self.root, new_node) | ||
| 91 | + self.node_count += 1 | ||
| 92 | + return True | ||
| 93 | + | ||
| 94 | + def search(self, file_name: str) -> Optional[TreeNode]: | ||
| 95 | + """根据文件名搜索节点""" | ||
| 96 | + def _search_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]: | ||
| 97 | + if node is None or node.file_name == target: | ||
| 98 | + return node | ||
| 99 | + if target < node.file_name: | ||
| 100 | + return _search_recursive(node.left, target) | ||
| 101 | + return _search_recursive(node.right, target) | ||
| 102 | + | ||
| 103 | + return _search_recursive(self.root, file_name) | ||
| 104 | + | ||
| 105 | + def delete(self, file_name: str) -> bool: | ||
| 106 | + """根据文件名删除节点""" | ||
| 107 | + if self.root is None: | ||
| 108 | + return False | ||
| 109 | + | ||
| 110 | + deleted = [False] # 使用列表作为可变对象传递 | ||
| 111 | + | ||
| 112 | + def _delete_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]: | ||
| 113 | + if node is None: | ||
| 114 | + return None | ||
| 115 | + | ||
| 116 | + if target < node.file_name: | ||
| 117 | + node.left = _delete_recursive(node.left, target) | ||
| 118 | + elif target > node.file_name: | ||
| 119 | + node.right = _delete_recursive(node.right, target) | ||
| 120 | + else: | ||
| 121 | + # 找到目标节点,执行删除 | ||
| 122 | + deleted[0] = True | ||
| 123 | + | ||
| 124 | + # 情况1: 没有子节点或只有一个子节点 | ||
| 125 | + if node.left is None: | ||
| 126 | + return node.right | ||
| 127 | + elif node.right is None: | ||
| 128 | + return node.left | ||
| 129 | + | ||
| 130 | + # 情况2: 有两个子节点,找到右子树中的最小节点 | ||
| 131 | + temp = self._find_min(node.right) | ||
| 132 | + node.file_path = temp.file_path | ||
| 133 | + node.file_name = temp.file_name | ||
| 134 | + node.is_directory = temp.is_directory | ||
| 135 | + node.size = temp.size | ||
| 136 | + node.created_time = temp.created_time | ||
| 137 | + node.right = _delete_recursive(node.right, temp.file_name) | ||
| 138 | + | ||
| 139 | + return node | ||
| 140 | + | ||
| 141 | + self.root = _delete_recursive(self.root, file_name) | ||
| 142 | + if deleted[0]: | ||
| 143 | + self.node_count -= 1 | ||
| 144 | + return deleted[0] | ||
| 145 | + | ||
| 146 | + def _find_min(self, node: TreeNode) -> TreeNode: | ||
| 147 | + """找到以node为根的子树中的最小节点""" | ||
| 148 | + current = node | ||
| 149 | + while current.left is not None: | ||
| 150 | + current = current.left | ||
| 151 | + return current | ||
| 152 | + | ||
| 153 | + def inorder_traversal(self) -> List[TreeNode]: | ||
| 154 | + """中序遍历(按文件名排序)""" | ||
| 155 | + result = [] | ||
| 156 | + | ||
| 157 | + def _inorder_recursive(node: Optional[TreeNode]): | ||
| 158 | + if node is not None: | ||
| 159 | + _inorder_recursive(node.left) | ||
| 160 | + result.append(node) | ||
| 161 | + _inorder_recursive(node.right) | ||
| 162 | + | ||
| 163 | + _inorder_recursive(self.root) | ||
| 164 | + return result | ||
| 165 | + | ||
| 166 | + def preorder_traversal(self) -> List[TreeNode]: | ||
| 167 | + """前序遍历""" | ||
| 168 | + result = [] | ||
| 169 | + | ||
| 170 | + def _preorder_recursive(node: Optional[TreeNode]): | ||
| 171 | + if node is not None: | ||
| 172 | + result.append(node) | ||
| 173 | + _preorder_recursive(node.left) | ||
| 174 | + _preorder_recursive(node.right) | ||
| 175 | + | ||
| 176 | + _preorder_recursive(self.root) | ||
| 177 | + return result | ||
| 178 | + | ||
| 179 | + def postorder_traversal(self) -> List[TreeNode]: | ||
| 180 | + """后序遍历""" | ||
| 181 | + result = [] | ||
| 182 | + | ||
| 183 | + def _postorder_recursive(node: Optional[TreeNode]): | ||
| 184 | + if node is not None: | ||
| 185 | + _postorder_recursive(node.left) | ||
| 186 | + _postorder_recursive(node.right) | ||
| 187 | + result.append(node) | ||
| 188 | + | ||
| 189 | + _postorder_recursive(self.root) | ||
| 190 | + return result | ||
| 191 | + | ||
| 192 | + def get_file_count(self) -> int: | ||
| 193 | + """获取文件总数""" | ||
| 194 | + return self.node_count | ||
| 195 | + | ||
| 196 | + def get_total_size(self) -> int: | ||
| 197 | + """获取所有文件的总大小""" | ||
| 198 | + def _sum_size_recursive(node: Optional[TreeNode]) -> int: | ||
| 199 | + if node is None: | ||
| 200 | + return 0 | ||
| 201 | + return node.size + _sum_size_recursive(node.left) + _sum_size_recursive(node.right) | ||
| 202 | + | ||
| 203 | + return _sum_size_recursive(self.root) | ||
| 204 | + | ||
| 205 | + def find_largest_file(self) -> Optional[TreeNode]: | ||
| 206 | + """查找最大的文件""" | ||
| 207 | + if self.root is None: | ||
| 208 | + return None | ||
| 209 | + | ||
| 210 | + largest = self.root | ||
| 211 | + | ||
| 212 | + def _find_largest_recursive(node: Optional[TreeNode]): | ||
| 213 | + nonlocal largest | ||
| 214 | + if node is None: | ||
| 215 | + return | ||
| 216 | + | ||
| 217 | + if not node.is_directory and node.size > largest.size: | ||
| 218 | + largest = node | ||
| 219 | + | ||
| 220 | + _find_largest_recursive(node.left) | ||
| 221 | + _find_largest_recursive(node.right) | ||
| 222 | + | ||
| 223 | + _find_largest_recursive(self.root) | ||
| 224 | + return largest | ||
| 225 | + | ||
| 226 | + def find_files_by_size(self, min_size: int, max_size: int) -> List[TreeNode]: | ||
| 227 | + """查找指定大小范围内的文件""" | ||
| 228 | + result = [] | ||
| 229 | + | ||
| 230 | + def _find_by_size_recursive(node: Optional[TreeNode]): | ||
| 231 | + if node is None: | ||
| 232 | + return | ||
| 233 | + | ||
| 234 | + if not node.is_directory and min_size <= node.size <= max_size: | ||
| 235 | + result.append(node) | ||
| 236 | + | ||
| 237 | + _find_by_size_recursive(node.left) | ||
| 238 | + _find_by_size_recursive(node.right) | ||
| 239 | + | ||
| 240 | + _find_by_size_recursive(self.root) | ||
| 241 | + return result | ||
| 242 | + | ||
| 243 | + | ||
| 244 | +class FileSystemIndexManager: | ||
| 245 | + """文件系统索引管理器,使用二叉搜索树实现""" | ||
| 246 | + | ||
| 247 | + def __init__(self): | ||
| 248 | + self.bst = BinarySearchTree() | ||
| 249 | + self.history = [] # 操作历史记录 | ||
| 250 | + | ||
| 251 | + def add_path(self, path: str) -> bool: | ||
| 252 | + """添加文件或目录到索引""" | ||
| 253 | + if not os.path.exists(path): | ||
| 254 | + print(f"错误: 路径不存在 - {path}") | ||
| 255 | + return False | ||
| 256 | + | ||
| 257 | + is_dir = os.path.isdir(path) | ||
| 258 | + success = self.bst.insert(path, is_dir) | ||
| 259 | + | ||
| 260 | + if success: | ||
| 261 | + action = f"添加 {'目录' if is_dir else '文件'}: {path}" | ||
| 262 | + self.history.append(action) | ||
| 263 | + print(f"成功: {action}") | ||
| 264 | + return success | ||
| 265 | + | ||
| 266 | + def add_directory_recursive(self, directory: str) -> int: | ||
| 267 | + """递归添加目录及其所有子目录和文件到索引""" | ||
| 268 | + if not os.path.isdir(directory): | ||
| 269 | + print(f"错误: 不是有效的目录 - {directory}") | ||
| 270 | + return 0 | ||
| 271 | + | ||
| 272 | + added_count = 0 | ||
| 273 | + | ||
| 274 | + # 首先添加根目录 | ||
| 275 | + if self.add_path(directory): | ||
| 276 | + added_count += 1 | ||
| 277 | + | ||
| 278 | + # 递归添加子目录和文件 | ||
| 279 | + for root, dirs, files in os.walk(directory): | ||
| 280 | + # 添加子目录 | ||
| 281 | + for dir_name in dirs: | ||
| 282 | + dir_path = os.path.join(root, dir_name) | ||
| 283 | + if self.add_path(dir_path): | ||
| 284 | + added_count += 1 | ||
| 285 | + | ||
| 286 | + # 添加文件 | ||
| 287 | + for file_name in files: | ||
| 288 | + file_path = os.path.join(root, file_name) | ||
| 289 | + if self.add_path(file_path): | ||
| 290 | + added_count += 1 | ||
| 291 | + | ||
| 292 | + action = f"递归添加目录: {directory},共添加 {added_count} 个项目" | ||
| 293 | + self.history.append(action) | ||
| 294 | + print(f"成功: {action}") | ||
| 295 | + return added_count | ||
| 296 | + | ||
| 297 | + def search_file(self, file_name: str) -> None: | ||
| 298 | + """搜索文件并显示结果""" | ||
| 299 | + node = self.bst.search(file_name) | ||
| 300 | + if node: | ||
| 301 | + print(f"找到文件: {node}") | ||
| 302 | + else: | ||
| 303 | + print(f"未找到文件: {file_name}") | ||
| 304 | + | ||
| 305 | + action = f"搜索文件: {file_name},结果: {'找到' if node else '未找到'}" | ||
| 306 | + self.history.append(action) | ||
| 307 | + | ||
| 308 | + def delete_file(self, file_name: str) -> None: | ||
| 309 | + """从索引中删除文件""" | ||
| 310 | + success = self.bst.delete(file_name) | ||
| 311 | + if success: | ||
| 312 | + print(f"成功删除文件: {file_name}") | ||
| 313 | + else: | ||
| 314 | + print(f"删除失败: 未找到文件 {file_name}") | ||
| 315 | + | ||
| 316 | + action = f"删除文件: {file_name},结果: {'成功' if success else '失败'}" | ||
| 317 | + self.history.append(action) | ||
| 318 | + | ||
| 319 | + def list_files(self, sort_order: str = "name") -> None: | ||
| 320 | + """列出所有文件""" | ||
| 321 | + if self.bst.get_file_count() == 0: | ||
| 322 | + print("索引中没有文件") | ||
| 323 | + return | ||
| 324 | + | ||
| 325 | + print("\n=== 文件列表 ===") | ||
| 326 | + print("类型 | 文件名 | 大小 | 创建时间") | ||
| 327 | + print("-" * 70) | ||
| 328 | + | ||
| 329 | + if sort_order == "name": | ||
| 330 | + nodes = self.bst.inorder_traversal() | ||
| 331 | + elif sort_order == "size": | ||
| 332 | + nodes = self.bst.inorder_traversal() | ||
| 333 | + nodes.sort(key=lambda x: x.size, reverse=True) | ||
| 334 | + elif sort_order == "created": | ||
| 335 | + nodes = self.bst.inorder_traversal() | ||
| 336 | + nodes.sort(key=lambda x: x.created_time, reverse=True) | ||
| 337 | + else: | ||
| 338 | + print(f"无效的排序顺序: {sort_order},使用默认排序(按名称)") | ||
| 339 | + nodes = self.bst.inorder_traversal() | ||
| 340 | + | ||
| 341 | + for node in nodes: | ||
| 342 | + print(node) | ||
| 343 | + | ||
| 344 | + print(f"\n总计: {self.bst.get_file_count()} 个项目,总大小: {node._format_size(self.bst.get_total_size())}") | ||
| 345 | + | ||
| 346 | + action = f"列出文件,排序方式: {sort_order}" | ||
| 347 | + self.history.append(action) | ||
| 348 | + | ||
| 349 | + def find_largest_files(self, count: int = 5) -> None: | ||
| 350 | + """查找最大的N个文件""" | ||
| 351 | + if self.bst.get_file_count() == 0: | ||
| 352 | + print("索引中没有文件") | ||
| 353 | + return | ||
| 354 | + | ||
| 355 | + all_files = [node for node in self.bst.inorder_traversal() if not node.is_directory] | ||
| 356 | + if not all_files: | ||
| 357 | + print("索引中没有文件,只有目录") | ||
| 358 | + return | ||
| 359 | + | ||
| 360 | + all_files.sort(key=lambda x: x.size, reverse=True) | ||
| 361 | + largest_files = all_files[:min(count, len(all_files))] | ||
| 362 | + | ||
| 363 | + print(f"\n=== 最大的 {len(largest_files)} 个文件 ===") | ||
| 364 | + print("文件名 | 大小 | 路径") | ||
| 365 | + print("-" * 70) | ||
| 366 | + | ||
| 367 | + for file in largest_files: | ||
| 368 | + print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}") | ||
| 369 | + | ||
| 370 | + action = f"查找最大的 {count} 个文件" | ||
| 371 | + self.history.append(action) | ||
| 372 | + | ||
| 373 | + def find_files_in_size_range(self, min_size: str, max_size: str) -> None: | ||
| 374 | + """查找指定大小范围内的文件""" | ||
| 375 | + def parse_size(size_str: str) -> int: | ||
| 376 | + """将人类可读的大小字符串解析为字节数""" | ||
| 377 | + size_str = size_str.strip().upper() | ||
| 378 | + if size_str.endswith('KB'): | ||
| 379 | + return int(float(size_str[:-2]) * 1024) | ||
| 380 | + elif size_str.endswith('MB'): | ||
| 381 | + return int(float(size_str[:-2]) * 1024 * 1024) | ||
| 382 | + elif size_str.endswith('GB'): | ||
| 383 | + return int(float(size_str[:-2]) * 1024 * 1024 * 1024) | ||
| 384 | + else: | ||
| 385 | + return int(size_str) | ||
| 386 | + | ||
| 387 | + try: | ||
| 388 | + min_bytes = parse_size(min_size) | ||
| 389 | + max_bytes = parse_size(max_size) | ||
| 390 | + | ||
| 391 | + if min_bytes > max_bytes: | ||
| 392 | + min_bytes, max_bytes = max_bytes, min_bytes | ||
| 393 | + print(f"注意: 自动交换了最小值和最大值,实际查找范围: {min_size} 到 {max_size}") | ||
| 394 | + | ||
| 395 | + files = self.bst.find_files_by_size(min_bytes, max_bytes) | ||
| 396 | + | ||
| 397 | + if not files: | ||
| 398 | + print(f"未找到大小在 {min_size} 到 {max_size} 范围内的文件") | ||
| 399 | + return | ||
| 400 | + | ||
| 401 | + print(f"\n=== 大小在 {min_size} 到 {max_size} 范围内的文件 ({len(files)} 个) ===") | ||
| 402 | + print("文件名 | 大小 | 路径") | ||
| 403 | + print("-" * 70) | ||
| 404 | + | ||
| 405 | + for file in files: | ||
| 406 | + print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}") | ||
| 407 | + | ||
| 408 | + action = f"查找大小在 {min_size} 到 {max_size} 范围内的文件,找到 {len(files)} 个" | ||
| 409 | + self.history.append(action) | ||
| 410 | + | ||
| 411 | + except ValueError: | ||
| 412 | + print(f"错误: 无法解析大小格式,请使用例如 '10MB', '2GB' 或 '5000' (字节)") | ||
| 413 | + | ||
| 414 | + def show_statistics(self) -> None: | ||
| 415 | + """显示索引统计信息""" | ||
| 416 | + file_count = self.bst.get_file_count() | ||
| 417 | + if file_count == 0: | ||
| 418 | + print("索引中没有文件") | ||
| 419 | + return | ||
| 420 | + | ||
| 421 | + total_size = self.bst.get_total_size() | ||
| 422 | + largest_file = self.bst.find_largest_file() | ||
| 423 | + | ||
| 424 | + print("\n=== 索引统计信息 ===") | ||
| 425 | + print(f"总项目数: {file_count}") | ||
| 426 | + print(f"总大小: {TreeNode('', False)._format_size(total_size)}") | ||
| 427 | + | ||
| 428 | + if largest_file: | ||
| 429 | + print(f"最大文件: {largest_file.file_name} ({TreeNode('', False)._format_size(largest_file.size)})") | ||
| 430 | + | ||
| 431 | + # 计算文件类型分布 | ||
| 432 | + file_types = {} | ||
| 433 | + for node in self.bst.inorder_traversal(): | ||
| 434 | + if not node.is_directory: | ||
| 435 | + ext = os.path.splitext(node.file_name)[1].lower() | ||
| 436 | + file_types[ext] = file_types.get(ext, 0) + 1 | ||
| 437 | + | ||
| 438 | + if file_types: | ||
| 439 | + print("\n文件类型分布:") | ||
| 440 | + for ext, count in sorted(file_types.items(), key=lambda x: x[1], reverse=True): | ||
| 441 | + print(f" {ext}: {count} 个文件") | ||
| 442 | + | ||
| 443 | + action = "显示索引统计信息" | ||
| 444 | + self.history.append(action) | ||
| 445 | + | ||
| 446 | + def show_history(self, limit: int = 10) -> None: | ||
| 447 | + """显示最近的操作历史""" | ||
| 448 | + print(f"\n=== 最近 {min(limit, len(self.history))} 条操作历史 ===") | ||
| 449 | + for i, action in enumerate(reversed(self.history[-limit:])): | ||
| 450 | + print(f"{len(self.history) - i}: {action}") | ||
| 451 | + | ||
| 452 | + | ||
| 453 | +def main(): | ||
| 454 | + """主函数,演示文件系统索引管理器的使用""" | ||
| 455 | + print("=== 文件系统索引管理器 (使用二叉搜索树实现) ===") | ||
| 456 | + | ||
| 457 | + manager = FileSystemIndexManager() | ||
| 458 | + | ||
| 459 | + # 示例:添加一些测试文件 | ||
| 460 | + test_files = [ | ||
| 461 | + ("C:/Users/Public/Documents", True), # 目录 | ||
| 462 | + ("C:/Windows/System32/drivers/etc/hosts", False), # 系统文件 | ||
| 463 | + ("C:/Program Files/Python310/LICENSE.txt", False), # 程序文件 | ||
| 464 | + ("C:/Windows/notepad.exe", False), # 可执行文件 | ||
| 465 | + ] | ||
| 466 | + | ||
| 467 | + print("\n--- 添加测试文件 ---") | ||
| 468 | + for path, is_dir in test_files: | ||
| 469 | + if os.path.exists(path): | ||
| 470 | + manager.add_path(path) | ||
| 471 | + else: | ||
| 472 | + print(f"跳过不存在的路径: {path}") | ||
| 473 | + | ||
| 474 | + # 示例:递归添加目录 | ||
| 475 | + print("\n--- 递归添加用户目录 ---") | ||
| 476 | + user_dir = os.path.expanduser("~") | ||
| 477 | + manager.add_directory_recursive(user_dir) | ||
| 478 | + | ||
| 479 | + # 示例:搜索文件 | ||
| 480 | + print("\n--- 搜索文件 ---") | ||
| 481 | + manager.search_file("hosts") | ||
| 482 | + manager.search_file("non_existent_file.txt") | ||
| 483 | + | ||
| 484 | + # 示例:列出文件 | ||
| 485 | + print("\n--- 列出文件 (按名称排序) ---") | ||
| 486 | + manager.list_files("name") | ||
| 487 | + | ||
| 488 | + print("\n--- 列出文件 (按大小排序) ---") | ||
| 489 | + manager.list_files("size") | ||
| 490 | + | ||
| 491 | + # 示例:查找最大的文件 | ||
| 492 | + print("\n--- 查找最大的文件 ---") | ||
| 493 | + manager.find_largest_files(3) | ||
| 494 | + | ||
| 495 | + # 示例:查找特定大小范围内的文件 | ||
| 496 | + print("\n--- 查找大小在 1MB 到 10MB 之间的文件 ---") | ||
| 497 | + manager.find_files_in_size_range("1MB", "10MB") | ||
| 498 | + | ||
| 499 | + # 示例:显示统计信息 | ||
| 500 | + print("\n--- 显示索引统计信息 ---") | ||
| 501 | + manager.show_statistics() | ||
| 502 | + | ||
| 503 | + # 示例:显示操作历史 | ||
| 504 | + print("\n--- 显示操作历史 ---") | ||
| 505 | + manager.show_history() | ||
| 506 | + | ||
| 507 | + # 示例:删除文件 | ||
| 508 | + print("\n--- 删除文件 ---") | ||
| 509 | + manager.delete_file("hosts") | ||
| 510 | + manager.search_file("hosts") # 验证已删除 | ||
| 511 | + | ||
| 512 | + print("\n=== 演示完成 ===") | ||
| 513 | + | ||
| 514 | + | ||
| 515 | +if __name__ == "__main__": | ||
| 516 | + main() | ||
| @@ -0,0 +1,518 @@ | |||
| 1 | +import os | ||
| 2 | +import time | ||
| 3 | +import random | ||
| 4 | +from typing import Optional, List, Tuple | ||
| 5 | + | ||
| 6 | +class TreeNode: | ||
| 7 | + """二叉搜索树节点,表示文件系统中的一个文件或目录""" | ||
| 8 | + | ||
| 9 | + def __init__(self, file_path: str, is_directory: bool = False): | ||
| 10 | + self.file_path = file_path | ||
| 11 | + self.file_name = os.path.basename(file_path) | ||
| 12 | + self.is_directory = is_directory | ||
| 13 | + self.size = self._calculate_size() | ||
| 14 | + self.created_time = time.time() | ||
| 15 | + self.left: Optional[TreeNode] = None | ||
| 16 | + self.right: Optional[TreeNode] = None | ||
| 17 | + | ||
| 18 | + def _calculate_size(self) -> int: | ||
| 19 | + """计算文件或目录的大小""" | ||
| 20 | + if not os.path.exists(self.file_path): | ||
| 21 | + return 0 | ||
| 22 | + | ||
| 23 | + if not self.is_directory: | ||
| 24 | + return os.path.getsize(self.file_path) | ||
| 25 | + | ||
| 26 | + # 递归计算目录大小 | ||
| 27 | + total_size = 0 | ||
| 28 | + for dirpath, _, filenames in os.walk(self.file_path): | ||
| 29 | + for f in filenames: | ||
| 30 | + fp = os.path.join(dirpath, f) | ||
| 31 | + try: | ||
| 32 | + total_size += os.path.getsize(fp) | ||
| 33 | + except OSError: | ||
| 34 | + pass | ||
| 35 | + return total_size | ||
| 36 | + | ||
| 37 | + def __str__(self) -> str: | ||
| 38 | + """节点的字符串表示""" | ||
| 39 | + node_type = "DIR" if self.is_directory else "FILE" | ||
| 40 | + size_str = self._format_size(self.size) | ||
| 41 | + created_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.created_time)) | ||
| 42 | + return f"{node_type} | {self.file_name} | {size_str} | {created_str}" | ||
| 43 | + | ||
| 44 | + def _format_size(self, size_bytes: int) -> str: | ||
| 45 | + """格式化文件大小为人类可读的形式""" | ||
| 46 | + if size_bytes < 1024: | ||
| 47 | + return f"{size_bytes} B" | ||
| 48 | + elif size_bytes < 1024 * 1024: | ||
| 49 | + return f"{size_bytes / 1024:.2f} KB" | ||
| 50 | + elif size_bytes < 1024 * 1024 * 1024: | ||
| 51 | + return f"{size_bytes / (1024 * 1024):.2f} MB" | ||
| 52 | + else: | ||
| 53 | + return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB" | ||
| 54 | + | ||
| 55 | + | ||
| 56 | +class BinarySearchTree: | ||
| 57 | + """二叉搜索树实现,用于文件系统索引管理""" | ||
| 58 | + | ||
| 59 | + def __init__(self): | ||
| 60 | + self.root: Optional[TreeNode] = None | ||
| 61 | + self.node_count = 0 | ||
| 62 | + | ||
| 63 | + def insert(self, file_path: str, is_directory: bool = False) -> bool: | ||
| 64 | + """插入文件或目录到二叉搜索树""" | ||
| 65 | + if not os.path.exists(file_path): | ||
| 66 | + print(f"错误: 文件或目录不存在 - {file_path}") | ||
| 67 | + return False | ||
| 68 | + | ||
| 69 | + new_node = TreeNode(file_path, is_directory) | ||
| 70 | + | ||
| 71 | + if self.root is None: | ||
| 72 | + self.root = new_node | ||
| 73 | + self.node_count += 1 | ||
| 74 | + return True | ||
| 75 | + | ||
| 76 | + # 递归插入 | ||
| 77 | + def _insert_recursive(node: TreeNode, new_node: TreeNode) -> TreeNode: | ||
| 78 | + if new_node.file_name < node.file_name: | ||
| 79 | + if node.left is None: | ||
| 80 | + node.left = new_node | ||
| 81 | + else: | ||
| 82 | + node.left = _insert_recursive(node.left, new_node) | ||
| 83 | + else: | ||
| 84 | + if node.right is None: | ||
| 85 | + node.right = new_node | ||
| 86 | + else: | ||
| 87 | + node.right = _insert_recursive(node.right, new_node) | ||
| 88 | + return node | ||
| 89 | + | ||
| 90 | + _insert_recursive(self.root, new_node) | ||
| 91 | + self.node_count += 1 | ||
| 92 | + return True | ||
| 93 | + | ||
| 94 | + def search(self, file_name: str) -> Optional[TreeNode]: | ||
| 95 | + """根据文件名搜索节点""" | ||
| 96 | + def _search_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]: | ||
| 97 | + if node is None or node.file_name == target: | ||
| 98 | + return node | ||
| 99 | + if target < node.file_name: | ||
| 100 | + return _search_recursive(node.left, target) | ||
| 101 | + return _search_recursive(node.right, target) | ||
| 102 | + | ||
| 103 | + return _search_recursive(self.root, file_name) | ||
| 104 | + | ||
| 105 | + def delete(self, file_name: str) -> bool: | ||
| 106 | + """根据文件名删除节点""" | ||
| 107 | + if self.root is None: | ||
| 108 | + return False | ||
| 109 | + | ||
| 110 | + deleted = [False] # 使用列表作为可变对象传递 | ||
| 111 | + | ||
| 112 | + def _delete_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]: | ||
| 113 | + if node is None: | ||
| 114 | + return None | ||
| 115 | + | ||
| 116 | + if target < node.file_name: | ||
| 117 | + node.left = _delete_recursive(node.left, target) | ||
| 118 | + elif target > node.file_name: | ||
| 119 | + node.right = _delete_recursive(node.right, target) | ||
| 120 | + else: | ||
| 121 | + # 找到目标节点,执行删除 | ||
| 122 | + deleted[0] = True | ||
| 123 | + | ||
| 124 | + # 情况1: 没有子节点或只有一个子节点 | ||
| 125 | + if node.left is None: | ||
| 126 | + return node.right | ||
| 127 | + elif node.right is None: | ||
| 128 | + return node.left | ||
| 129 | + | ||
| 130 | + # 情况2: 有两个子节点,找到右子树中的最小节点 | ||
| 131 | + temp = self._find_min(node.right) | ||
| 132 | + node.file_path = temp.file_path | ||
| 133 | + node.file_name = temp.file_name | ||
| 134 | + node.is_directory = temp.is_directory | ||
| 135 | + node.size = temp.size | ||
| 136 | + node.created_time = temp.created_time | ||
| 137 | + node.right = _delete_recursive(node.right, temp.file_name) | ||
| 138 | + | ||
| 139 | + return node | ||
| 140 | + | ||
| 141 | + self.root = _delete_recursive(self.root, file_name) | ||
| 142 | + if deleted[0]: | ||
| 143 | + self.node_count -= 1 | ||
| 144 | + return deleted[0] | ||
| 145 | + | ||
| 146 | + def _find_min(self, node: TreeNode) -> TreeNode: | ||
| 147 | + """找到以node为根的子树中的最小节点""" | ||
| 148 | + current = node | ||
| 149 | + while current.left is not None: | ||
| 150 | + current = current.left | ||
| 151 | + return current | ||
| 152 | + | ||
| 153 | + def inorder_traversal(self) -> List[TreeNode]: | ||
| 154 | + """中序遍历(按文件名排序)""" | ||
| 155 | + result = [] | ||
| 156 | + | ||
| 157 | + def _inorder_recursive(node: Optional[TreeNode]): | ||
| 158 | + if node is not None: | ||
| 159 | + _inorder_recursive(node.left) | ||
| 160 | + result.append(node) | ||
| 161 | + _inorder_recursive(node.right) | ||
| 162 | + | ||
| 163 | + _inorder_recursive(self.root) | ||
| 164 | + return result | ||
| 165 | + | ||
| 166 | + def preorder_traversal(self) -> List[TreeNode]: | ||
| 167 | + """前序遍历""" | ||
| 168 | + result = [] | ||
| 169 | + | ||
| 170 | + def _preorder_recursive(node: Optional[TreeNode]): | ||
| 171 | + if node is not None: | ||
| 172 | + result.append(node) | ||
| 173 | + _preorder_recursive(node.left) | ||
| 174 | + _preorder_recursive(node.right) | ||
| 175 | + | ||
| 176 | + _preorder_recursive(self.root) | ||
| 177 | + return result | ||
| 178 | + | ||
| 179 | + def postorder_traversal(self) -> List[TreeNode]: | ||
| 180 | + """后序遍历""" | ||
| 181 | + result = [] | ||
| 182 | + | ||
| 183 | + def _postorder_recursive(node: Optional[TreeNode]): | ||
| 184 | + if node is not None: | ||
| 185 | + _postorder_recursive(node.left) | ||
| 186 | + _postorder_recursive(node.right) | ||
| 187 | + result.append(node) | ||
| 188 | + | ||
| 189 | + _postorder_recursive(self.root) | ||
| 190 | + return result | ||
| 191 | + | ||
| 192 | + def get_file_count(self) -> int: | ||
| 193 | + """获取文件总数""" | ||
| 194 | + return self.node_count | ||
| 195 | + | ||
| 196 | + def get_total_size(self) -> int: | ||
| 197 | + """获取所有文件的总大小""" | ||
| 198 | + def _sum_size_recursive(node: Optional[TreeNode]) -> int: | ||
| 199 | + if node is None: | ||
| 200 | + return 0 | ||
| 201 | + return node.size + _sum_size_recursive(node.left) + _sum_size_recursive(node.right) | ||
| 202 | + | ||
| 203 | + return _sum_size_recursive(self.root) | ||
| 204 | + | ||
| 205 | + def find_largest_file(self) -> Optional[TreeNode]: | ||
| 206 | + """查找最大的文件""" | ||
| 207 | + if self.root is None: | ||
| 208 | + return None | ||
| 209 | + | ||
| 210 | + largest = self.root | ||
| 211 | + | ||
| 212 | + def _find_largest_recursive(node: Optional[TreeNode]): | ||
| 213 | + nonlocal largest | ||
| 214 | + if node is None: | ||
| 215 | + return | ||
| 216 | + | ||
| 217 | + if not node.is_directory and node.size > largest.size: | ||
| 218 | + largest = node | ||
| 219 | + | ||
| 220 | + _find_largest_recursive(node.left) | ||
| 221 | + _find_largest_recursive(node.right) | ||
| 222 | + | ||
| 223 | + _find_largest_recursive(self.root) | ||
| 224 | + return largest | ||
| 225 | + | ||
| 226 | + def find_files_by_size(self, min_size: int, max_size: int) -> List[TreeNode]: | ||
| 227 | + """查找指定大小范围内的文件""" | ||
| 228 | + result = [] | ||
| 229 | + | ||
| 230 | + def _find_by_size_recursive(node: Optional[TreeNode]): | ||
| 231 | + if node is None: | ||
| 232 | + return | ||
| 233 | + | ||
| 234 | + if not node.is_directory and min_size <= node.size <= max_size: | ||
| 235 | + result.append(node) | ||
| 236 | + | ||
| 237 | + _find_by_size_recursive(node.left) | ||
| 238 | + _find_by_size_recursive(node.right) | ||
| 239 | + | ||
| 240 | + _find_by_size_recursive(self.root) | ||
| 241 | + return result | ||
| 242 | + | ||
| 243 | + | ||
| 244 | +class FileSystemIndexManager: | ||
| 245 | + """文件系统索引管理器,使用二叉搜索树实现""" | ||
| 246 | + | ||
| 247 | + def __init__(self): | ||
| 248 | + self.bst = BinarySearchTree() | ||
| 249 | + self.history = [] # 操作历史记录 | ||
| 250 | + | ||
| 251 | + def add_path(self, path: str) -> bool: | ||
| 252 | + """添加文件或目录到索引""" | ||
| 253 | + if not os.path.exists(path): | ||
| 254 | + print(f"错误: 路径不存在 - {path}") | ||
| 255 | + return False | ||
| 256 | + | ||
| 257 | + is_dir = os.path.isdir(path) | ||
| 258 | + success = self.bst.insert(path, is_dir) | ||
| 259 | + | ||
| 260 | + if success: | ||
| 261 | + action = f"添加 {'目录' if is_dir else '文件'}: {path}" | ||
| 262 | + self.history.append(action) | ||
| 263 | + print(f"成功: {action}") | ||
| 264 | + return success | ||
| 265 | + | ||
| 266 | + def add_directory_recursive(self, directory: str) -> int: | ||
| 267 | + """递归添加目录及其所有子目录和文件到索引""" | ||
| 268 | + if not os.path.isdir(directory): | ||
| 269 | + print(f"错误: 不是有效的目录 - {directory}") | ||
| 270 | + return 0 | ||
| 271 | + | ||
| 272 | + added_count = 0 | ||
| 273 | + | ||
| 274 | + # 首先添加根目录 | ||
| 275 | + if self.add_path(directory): | ||
| 276 | + added_count += 1 | ||
| 277 | + | ||
| 278 | + # 递归添加子目录和文件 | ||
| 279 | + for root, dirs, files in os.walk(directory): | ||
| 280 | + # 添加子目录 | ||
| 281 | + for dir_name in dirs: | ||
| 282 | + dir_path = os.path.join(root, dir_name) | ||
| 283 | + if self.add_path(dir_path): | ||
| 284 | + added_count += 1 | ||
| 285 | + | ||
| 286 | + # 添加文件 | ||
| 287 | + for file_name in files: | ||
| 288 | + file_path = os.path.join(root, file_name) | ||
| 289 | + if self.add_path(file_path): | ||
| 290 | + added_count += 1 | ||
| 291 | + | ||
| 292 | + action = f"递归添加目录: {directory},共添加 {added_count} 个项目" | ||
| 293 | + self.history.append(action) | ||
| 294 | + print(f"成功: {action}") | ||
| 295 | + return added_count | ||
| 296 | + | ||
| 297 | + def search_file(self, file_name: str) -> None: | ||
| 298 | + """搜索文件并显示结果""" | ||
| 299 | + node = self.bst.search(file_name) | ||
| 300 | + if node: | ||
| 301 | + print(f"找到文件: {node}") | ||
| 302 | + else: | ||
| 303 | + print(f"未找到文件: {file_name}") | ||
| 304 | + | ||
| 305 | + action = f"搜索文件: {file_name},结果: {'找到' if node else '未找到'}" | ||
| 306 | + self.history.append(action) | ||
| 307 | + | ||
| 308 | + def delete_file(self, file_name: str) -> None: | ||
| 309 | + """从索引中删除文件""" | ||
| 310 | + success = self.bst.delete(file_name) | ||
| 311 | + if success: | ||
| 312 | + print(f"成功删除文件: {file_name}") | ||
| 313 | + else: | ||
| 314 | + print(f"删除失败: 未找到文件 {file_name}") | ||
| 315 | + | ||
| 316 | + action = f"删除文件: {file_name},结果: {'成功' if success else '失败'}" | ||
| 317 | + self.history.append(action) | ||
| 318 | + | ||
| 319 | + def list_files(self, sort_order: str = "name") -> None: | ||
| 320 | + """列出所有文件""" | ||
| 321 | + if self.bst.get_file_count() == 0: | ||
| 322 | + print("索引中没有文件") | ||
| 323 | + return | ||
| 324 | + | ||
| 325 | + print("\n=== 文件列表 ===") | ||
| 326 | + print("类型 | 文件名 | 大小 | 创建时间") | ||
| 327 | + print("-" * 70) | ||
| 328 | + | ||
| 329 | + if sort_order == "name": | ||
| 330 | + nodes = self.bst.inorder_traversal() | ||
| 331 | + elif sort_order == "size": | ||
| 332 | + nodes = self.bst.inorder_traversal() | ||
| 333 | + nodes.sort(key=lambda x: x.size, reverse=True) | ||
| 334 | + elif sort_order == "created": | ||
| 335 | + nodes = self.bst.inorder_traversal() | ||
| 336 | + nodes.sort(key=lambda x: x.created_time, reverse=True) | ||
| 337 | + else: | ||
| 338 | + print(f"无效的排序顺序: {sort_order},使用默认排序(按名称)") | ||
| 339 | + nodes = self.bst.inorder_traversal() | ||
| 340 | + | ||
| 341 | + for node in nodes: | ||
| 342 | + print(node) | ||
| 343 | + | ||
| 344 | + print(f"\n总计: {self.bst.get_file_count()} 个项目,总大小: {node._format_size(self.bst.get_total_size())}") | ||
| 345 | + | ||
| 346 | + action = f"列出文件,排序方式: {sort_order}" | ||
| 347 | + self.history.append(action) | ||
| 348 | + | ||
| 349 | + def find_largest_files(self, count: int = 5) -> None: | ||
| 350 | + """查找最大的N个文件""" | ||
| 351 | + if self.bst.get_file_count() == 0: | ||
| 352 | + print("索引中没有文件") | ||
| 353 | + return | ||
| 354 | + | ||
| 355 | + all_files = [node for node in self.bst.inorder_traversal() if not node.is_directory] | ||
| 356 | + if not all_files: | ||
| 357 | + print("索引中没有文件,只有目录") | ||
| 358 | + return | ||
| 359 | + | ||
| 360 | + all_files.sort(key=lambda x: x.size, reverse=True) | ||
| 361 | + largest_files = all_files[:min(count, len(all_files))] | ||
| 362 | + | ||
| 363 | + print(f"\n=== 最大的 {len(largest_files)} 个文件 ===") | ||
| 364 | + print("文件名 | 大小 | 路径") | ||
| 365 | + print("-" * 70) | ||
| 366 | + | ||
| 367 | + for file in largest_files: | ||
| 368 | + print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}") | ||
| 369 | + | ||
| 370 | + action = f"查找最大的 {count} 个文件" | ||
| 371 | + self.history.append(action) | ||
| 372 | + | ||
| 373 | + def find_files_in_size_range(self, min_size: str, max_size: str) -> None: | ||
| 374 | + """查找指定大小范围内的文件""" | ||
| 375 | + def parse_size(size_str: str) -> int: | ||
| 376 | + """将人类可读的大小字符串解析为字节数""" | ||
| 377 | + size_str = size_str.strip().upper() | ||
| 378 | + if size_str.endswith('KB'): | ||
| 379 | + return int(float(size_str[:-2]) * 1024) | ||
| 380 | + elif size_str.endswith('MB'): | ||
| 381 | + return int(float(size_str[:-2]) * 1024 * 1024) | ||
| 382 | + elif size_str.endswith('GB'): | ||
| 383 | + return int(float(size_str[:-2]) * 1024 * 1024 * 1024) | ||
| 384 | + else: | ||
| 385 | + return int(size_str) | ||
| 386 | + | ||
| 387 | + try: | ||
| 388 | + min_bytes = parse_size(min_size) | ||
| 389 | + max_bytes = parse_size(max_size) | ||
| 390 | + | ||
| 391 | + if min_bytes > max_bytes: | ||
| 392 | + min_bytes, max_bytes = max_bytes, min_bytes | ||
| 393 | + print(f"注意: 自动交换了最小值和最大值,实际查找范围: {min_size} 到 {max_size}") | ||
| 394 | + | ||
| 395 | + files = self.bst.find_files_by_size(min_bytes, max_bytes) | ||
| 396 | + | ||
| 397 | + if not files: | ||
| 398 | + print(f"未找到大小在 {min_size} 到 {max_size} 范围内的文件") | ||
| 399 | + return | ||
| 400 | + | ||
| 401 | + print(f"\n=== 大小在 {min_size} 到 {max_size} 范围内的文件 ({len(files)} 个) ===") | ||
| 402 | + print("文件名 | 大小 | 路径") | ||
| 403 | + print("-" * 70) | ||
| 404 | + | ||
| 405 | + for file in files: | ||
| 406 | + print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}") | ||
| 407 | + | ||
| 408 | + action = f"查找大小在 {min_size} 到 {max_size} 范围内的文件,找到 {len(files)} 个" | ||
| 409 | + self.history.append(action) | ||
| 410 | + | ||
| 411 | + except ValueError: | ||
| 412 | + print(f"错误: 无法解析大小格式,请使用例如 '10MB', '2GB' 或 '5000' (字节)") | ||
| 413 | + | ||
| 414 | + def show_statistics(self) -> None: | ||
| 415 | + """显示索引统计信息""" | ||
| 416 | + file_count = self.bst.get_file_count() | ||
| 417 | + if file_count == 0: | ||
| 418 | + print("索引中没有文件") | ||
| 419 | + return | ||
| 420 | + | ||
| 421 | + total_size = self.bst.get_total_size() | ||
| 422 | + largest_file = self.bst.find_largest_file() | ||
| 423 | + | ||
| 424 | + print("\n=== 索引统计信息 ===") | ||
| 425 | + print(f"总项目数: {file_count}") | ||
| 426 | + print(f"总大小: {TreeNode('', False)._format_size(total_size)}") | ||
| 427 | + | ||
| 428 | + if largest_file: | ||
| 429 | + print(f"最大文件: {largest_file.file_name} ({TreeNode('', False)._format_size(largest_file.size)})") | ||
| 430 | + | ||
| 431 | + # 计算文件类型分布 | ||
| 432 | + file_types = {} | ||
| 433 | + for node in self.bst.inorder_traversal(): | ||
| 434 | + if not node.is_directory: | ||
| 435 | + ext = os.path.splitext(node.file_name)[1].lower() | ||
| 436 | + file_types[ext] = file_types.get(ext, 0) + 1 | ||
| 437 | + | ||
| 438 | + if file_types: | ||
| 439 | + print("\n文件类型分布:") | ||
| 440 | + for ext, count in sorted(file_types.items(), key=lambda x: x[1], reverse=True): | ||
| 441 | + print(f" {ext}: {count} 个文件") | ||
| 442 | + | ||
| 443 | + action = "显示索引统计信息" | ||
| 444 | + self.history.append(action) | ||
| 445 | + | ||
| 446 | + def show_history(self, limit: int = 10) -> None: | ||
| 447 | + """显示最近的操作历史""" | ||
| 448 | + print(f"\n=== 最近 {min(limit, len(self.history))} 条操作历史 ===") | ||
| 449 | + for i, action in enumerate(reversed(self.history[-limit:])): | ||
| 450 | + print(f"{len(self.history) - i}: {action}") | ||
| 451 | + | ||
| 452 | + | ||
| 453 | +def main(): | ||
| 454 | + """主函数,演示文件系统索引管理器的使用""" | ||
| 455 | + print("=== 文件系统索引管理器 (使用二叉搜索树实现) ===") | ||
| 456 | + | ||
| 457 | + manager = FileSystemIndexManager() | ||
| 458 | + | ||
| 459 | + # 示例:添加一些测试文件 | ||
| 460 | + test_files = [ | ||
| 461 | + ("C:/Users/Public/Documents", True), # 目录 | ||
| 462 | + ("C:/Windows/System32/drivers/etc/hosts", False), # 系统文件 | ||
| 463 | + ("C:/Program Files/Python310/LICENSE.txt", False), # 程序文件 | ||
| 464 | + ("C:/Windows/notepad.exe", False), # 可执行文件 | ||
| 465 | + ] | ||
| 466 | + | ||
| 467 | + print("\n--- 添加测试文件 ---") | ||
| 468 | + for path, is_dir in test_files: | ||
| 469 | + if os.path.exists(path): | ||
| 470 | + manager.add_path(path) | ||
| 471 | + else: | ||
| 472 | + print(f"跳过不存在的路径: {path}") | ||
| 473 | + | ||
| 474 | + # 示例:递归添加目录 | ||
| 475 | + print("\n--- 递归添加用户目录 ---") | ||
| 476 | + user_dir = os.path.expanduser("~") | ||
| 477 | + manager.add_directory_recursive(user_dir) | ||
| 478 | + | ||
| 479 | + # 示例:搜索文件 | ||
| 480 | + print("\n--- 搜索文件 ---") | ||
| 481 | + manager.search_file("hosts") | ||
| 482 | + manager.search_file("non_existent_file.txt") | ||
| 483 | + | ||
| 484 | + # 示例:列出文件 | ||
| 485 | + print("\n--- 列出文件 (按名称排序) ---") | ||
| 486 | + manager.list_files("name") | ||
| 487 | + | ||
| 488 | + print("\n--- 列出文件 (按大小排序) ---") | ||
| 489 | + manager.list_files("size") | ||
| 490 | + | ||
| 491 | + # 示例:查找最大的文件 | ||
| 492 | + print("\n--- 查找最大的文件 ---") | ||
| 493 | + manager.find_largest_files(3) | ||
| 494 | + | ||
| 495 | + # 示例:查找特定大小范围内的文件 | ||
| 496 | + print("\n--- 查找大小在 1MB 到 10MB 之间的文件 ---") | ||
| 497 | + manager.find_files_in_size_range("1MB", "10MB") | ||
| 498 | + | ||
| 499 | + # 示例:显示统计信息 | ||
| 500 | + print("\n--- 显示索引统计信息 ---") | ||
| 501 | + manager.show_statistics() | ||
| 502 | + | ||
| 503 | + # 示例:显示操作历史 | ||
| 504 | + print("\n--- 显示操作历史 ---") | ||
| 505 | + manager.show_history() | ||
| 506 | + | ||
| 507 | + # 示例:删除文件 | ||
| 508 | + print("\n--- 删除文件 ---") | ||
| 509 | + manager.delete_file("hosts") | ||
| 510 | + manager.search_file("hosts") # 验证已删除 | ||
| 511 | + | ||
| 512 | + print("\n=== 演示完成 ===") | ||
| 513 | + | ||
| 514 | + | ||
| 515 | +if __name__ == "__main__": | ||
| 516 | + main() | ||
| 517 | + | ||
| 518 | + | ||