Windows 10下使用Dart编辑隐藏文件失败的原因咨询
在Windows 10环境下,我编写了如下Dart代码:
import 'dart:io'; void main(List<String> args) { File('C:\\Users\\alexa\\Documents\\test\\my-file.txt').writeAsString("some-text"); // 文件隐藏时报错,不隐藏时正常 }
当文件未设置隐藏属性时,代码可正常运行;但文件设置为隐藏后,执行代码抛出错误:
Unhandled Exception: PathAccessException: Cannot open file, path = 'C:\Users\alexa\Documents\test\my-file.txt' (OS Error: 拒绝访问。 , errno = 5)
而使用如下代码读取该隐藏文件时却能正常获取数据:
import 'dart:io'; void main(List<String> args) { File('C:\\Users\\alexa\\Documents\\test\\my-file.txt').readAsStringSync(); // 即使是隐藏文件也能正常工作 }
两种操作下,文件均未设置只读属性,仅带有+H隐藏属性。相关属性说明如下:
+R - 使用+R选项将文件设为只读。只读文件可读取,但无法修改或删除。
-R - 使用-R选项将文件保护属性恢复为正常状态(可读取、修改或删除)。
+A - 使用+A选项设置文件的存档属性。设置后,使用BACKUP或XCOPY命令时该文件会被标记为可存档。
-A - 使用-A选项关闭存档属性。
+H - 在DOS 4到6版本中,使用+H选项设置文件的隐藏属性,使其不会出现在目录列表中。
-H - 使用-H选项关闭隐藏属性。
+S - 在DOS 4之后的版本中,使用+S选项设置文件的系统属性。设置后,该文件会被标记为仅DOS使用的命令文件,不会出现在目录列表中,此属性通常为程序员保留。
-S - 使用-S选项关闭系统属性。
/S - 使用/S开关为指定路径下的子目录设置属性。
请问为什么无法使用Dart编辑该隐藏文件?
原因分析
这是因为Dart的File.writeAsString()方法在Windows系统下打开隐藏文件时,默认未请求足够权限。Windows对隐藏文件的写入操作需要显式声明允许修改隐藏属性的权限,而读取操作无需额外权限,因此读取能正常进行。
Dart的dart:io底层调用Windows API,写入隐藏文件时需要在打开文件时指定FILE_FLAG_BACKUP_SEMANTICS标志,或者先移除隐藏属性再写入,完成后恢复属性。
解决方法
临时移除隐藏属性再写入
先获取文件当前属性,移除隐藏属性后写入,完成后恢复原属性:import 'dart:io'; import 'dart:ffi'; import 'package:win32/win32.dart'; void main(List<String> args) { final file = File('C:\\Users\\alexa\\Documents\\test\\my-file.txt'); final path = file.path; // 获取当前文件属性 final attributes = GetFileAttributes(path); if (attributes == INVALID_FILE_ATTRIBUTES) { throw Exception('获取文件属性失败'); } // 移除隐藏属性(如果存在) final hasHiddenAttr = (attributes & FILE_ATTRIBUTE_HIDDEN) != 0; if (hasHiddenAttr) { SetFileAttributes(path, attributes & ~FILE_ATTRIBUTE_HIDDEN); } // 写入文件内容 file.writeAsStringSync("some-text"); // 恢复隐藏属性 if (hasHiddenAttr) { SetFileAttributes(path, attributes); } }需在
pubspec.yaml中添加win32依赖:dependencies: win32: ^5.0.0通过底层API指定权限打开文件
使用win32库直接调用CreateFile函数,指定FILE_FLAG_BACKUP_SEMANTICS标志打开隐藏文件,再执行写入操作。这种方式无需修改文件属性,但实现相对复杂。
内容的提问来源于stack exchange,提问作者Lenny4

