ZetCode

Dart FileSystemMoveEvent

最后修改于 2025 年 4 月 4 日

Dart 中的 FileSystemMoveEvent 类代表文件系统移动或重命名操作。它是 Dart 文件系统事件监控 API 的一部分。

当文件或目录在被监视的目录内被移动或重命名时,会触发此事件。它提供了有关旧路径和新路径的详细信息。

基本定义

FileSystemMoveEventFileSystemEvent 的子类。它包含有关文件系统中文件/目录移动操作的信息。

主要属性包括移动项的旧路径(源)和新路径(目标)。当发生移动时,它由 Directory.watch() 发出。

基本的 FileSystemMoveEvent 用法

此示例显示了如何监视目录中的文件移动事件。

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('test_dir');
  await dir.create();
  
  var watcher = dir.watch();
  watcher.listen((event) {
    if (event is FileSystemMoveEvent) {
      print('Move detected:');
      print('  From: ${event.path}');
      print('  To: ${event.destination}');
      print('  Type: ${event.type}');
    }
  });
  
  // Simulate a file move
  var file = File('${dir.path}/test.txt');
  await file.create();
  await file.rename('${dir.path}/renamed.txt');
}

我们创建一个目录监视器并监听移动事件。当文件被重命名时,事件会同时提供原始路径和新路径。类型表示移动或重命名。

$ dart main.dart
Move detected:
  From: test_dir/test.txt
  To: test_dir/renamed.txt
  Type: FileSystemEvent.move

处理目录移动

此示例演示了如何检测目录移动操作。

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('watch_dir');
  await dir.create();
  
  var watcher = dir.watch();
  watcher.listen((event) {
    if (event is FileSystemMoveEvent) {
      print('Directory moved:');
      print('  Source: ${event.path}');
      print('  Target: ${event.destination}');
    }
  });
  
  // Create and move a subdirectory
  var subDir = Directory('${dir.path}/subdir');
  await subDir.create();
  await subDir.rename('${dir.path}/moved_subdir');
}

目录移动会触发与文件移动类似的事件。事件包含被移动目录的原始路径和新路径。这可以递归工作。

$ dart main.dart
Directory moved:
  Source: watch_dir/subdir
  Target: watch_dir/moved_subdir

区分移动类型

此示例展示了如何区分移动和重命名。

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('monitor_dir');
  await dir.create();
  
  var watcher = dir.watch();
  watcher.listen((event) {
    if (event is FileSystemMoveEvent) {
      var isRename = event.path.split('/').last == 
                    event.destination.split('/').last;
      
      print(isRename ? 'File renamed' : 'File moved');
      print('  Old: ${event.path}');
      print('  New: ${event.destination}');
    }
  });
  
  // Test cases
  var file = File('${dir.path}/original.txt');
  await file.create();
  
  // Rename (same directory)
  await file.rename('${dir.path}/renamed.txt');
  
  // Move (different directory)
  var newDir = Directory('${dir.path}/new_location');
  await newDir.create();
  await File('${dir.path}/renamed.txt')
      .rename('${newDir.path}/moved.txt');
}

我们通过比较父目录来区分重命名和移动。重命名保持相同的父目录,而移动会改变它。两者都会触发移动事件。

$ dart main.dart
File renamed
  Old: monitor_dir/original.txt
  New: monitor_dir/renamed.txt
File moved
  Old: monitor_dir/renamed.txt
  New: monitor_dir/new_location/moved.txt

移动事件中的错误处理

此示例演示了在文件系统移动操作期间的错误处理。

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('error_dir');
  await dir.create();
  
  var watcher = dir.watch();
  watcher.listen((event) {
    if (event is FileSystemMoveEvent) {
      print('Move event detected');
      try {
        var file = File(event.destination);
        print('File exists: ${file.existsSync()}');
      } catch (e) {
        print('Error checking moved file: $e');
      }
    }
  });
  
  var file = File('${dir.path}/testfile.txt');
  await file.create();
  
  // Move to invalid location
  try {
    await file.rename('${dir.path}/nonexistent/subdir/file.txt');
  } catch (e) {
    print('Move failed: $e');
  }
}

我们处理处理移动事件时可能发生的错误。即使移动操作失败,事件也会触发,因此目标验证很重要。

$ dart main.dart
Move event detected
Error checking moved file: FileSystemException: Cannot open file, path = 'error_dir/nonexistent/subdir/file.txt' (OS Error: No such file or directory, errno = 2)
Move failed: FileSystemException: Cannot rename file to 'error_dir/nonexistent/subdir/file.txt', path = 'error_dir/testfile.txt' (OS Error: No such file or directory, errno = 2)

监视多个事件

此示例显示了如何处理包括移动事件在内的多种事件类型。

main.dart
import 'dart:io';

void main() async {
  var dir = Directory('multi_event_dir');
  await dir.create();
  
  var watcher = dir.watch();
  watcher.listen((event) {
    switch (event.type) {
      case FileSystemEvent.move:
        print('Move event: ${event.path} → ${(event as FileSystemMoveEvent).destination}');
        break;
      case FileSystemEvent.create:
        print('Create event: ${event.path}');
        break;
      case FileSystemEvent.delete:
        print('Delete event: ${event.path}');
        break;
      case FileSystemEvent.modify:
        print('Modify event: ${event.path}');
        break;
    }
  });
  
  // Trigger various events
  var file = File('${dir.path}/demo.txt');
  await file.create();
  await file.writeAsString('content');
  await file.rename('${dir.path}/renamed_demo.txt');
  await file.delete();
}

我们使用 switch 语句处理所有文件系统事件类型。移动事件被专门转换为以访问目标属性。每种事件类型都有自己的 case。

$ dart main.dart
Create event: multi_event_dir/demo.txt
Modify event: multi_event_dir/demo.txt
Move event: multi_event_dir/demo.txt → multi_event_dir/renamed_demo.txt
Delete event: multi_event_dir/renamed_demo.txt

最佳实践

来源

Dart FileSystemMoveEvent 文档

本教程通过实际示例介绍了 Dart 的 FileSystemMoveEvent 类,展示了文件和目录移动的检测、错误处理和事件处理。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出 所有 Dart 教程