Flutter existSync无法识别Mac下Office临时锁定文件问题
Mac下Office临时文件
existsSync()偶尔判断失败的解决方案 可能的触发原因
- 文件系统元数据缓存:Mac的APFS等文件系统存在元数据缓存机制,导致
existsSync()无法立即检测到刚创建的临时文件。 - 临时文件动态生命周期:Office会频繁创建、修改或锁定临时文件,在文件处于写入、锁定状态时,同步API可能无法正确识别其存在。
- 命名规则覆盖不全:当前仅处理了“加
~$前缀并移除原文件名前两个字符”的情况,但Office的命名逻辑可能因文件名长度阈值(字节数而非字符数)、版本差异存在其他变体。
针对性解决方案
1. 增加重试机制
针对文件系统延迟问题,添加有限次数的重试,给文件系统足够的元数据同步时间:
bool isOfficeLockFilePresent(String dirPath, String fileName) { final lockFileName = "~\$${fileName.substring(2)}"; final lockFile = File("$dirPath/$lockFileName"); // 最多重试3次,每次间隔100ms for (int retry = 0; retry < 3; retry++) { if (lockFile.existsSync()) return true; sleep(const Duration(milliseconds: 100)); } return false; }
2. 遍历目录匹配所有~$开头文件
避免依赖单一命名规则,直接扫描目标目录下的Office临时文件,反向匹配原文件:
bool matchOfficeLockFile(String dirPath, String originalFileName) { final dir = Directory(dirPath); if (!dir.existsSync()) return false; // 筛选所有~$开头的文件 final lockFiles = dir.listSync().where((entity) { return entity is File && entity.path.split('/').last.startsWith('~$'); }).cast<File>().toList(); for (final file in lockFiles) { final lockFileName = file.path.split('/').last; String candidateOriginal; // 处理两种核心命名场景 if (lockFileName.length == originalFileName.length + 2) { // 仅添加~$前缀的情况 candidateOriginal = lockFileName.substring(2); } else if (lockFileName.length == originalFileName.length) { // 添加前缀并移除原文件名前两个字符的情况 candidateOriginal = originalFileName.substring(0, 2) + lockFileName.substring(2); } else { continue; } if (candidateOriginal == originalFileName) return true; } return false; }
3. 验证目录访问权限
确保你的应用拥有目标目录的访问权限(比如Mac隐私设置中允许访问Documents、Desktop等目录),权限不足会导致existsSync()返回错误的false结果。
内容的提问来源于stack exchange,提问作者Fraser Steel
相关产品推荐
相关产品推荐

