我今天在Dart迈出了第一步,我不知道如何继续的第一件事是如何测试作为参数传递给我正在编写的CLI工具的文件是否可写。< / p>
所以我的想法是我有一个接受input
目录和输出文件名的工具。它的作用是解析输入目录中的一些文件,将数据编译成有意义的JSON配置并将其保存在output
文件中。
但是,在执行任何操作之前,我想运行一个完整性检查,以查看给定的输出文件参数实际上可以用作可写文件。
我决定解决这个问题的方法是在try-catch块中打开Append文件:
try {
new File(output).writeAsStringSync('', mode: FileMode.APPEND, flush: true);
} on FileSystemException catch(e) {
// do something
}
但是,我不喜欢这个解决方案。主要是它创建一个文件,如果它尚不存在。另外,当我只想知道它是否可写时,我不明白为什么我应该在文件中写任何东西。
在Dart中做这件事的正确方法是什么?
答案 0 :(得分:4)
您可以使用file.statSync().mode
或file.statSync().modeString()
。请参阅FileStat。
答案 1 :(得分:1)
实际上很难用任何一种语言可靠地做到这一点。正如 Eiko 所指出的那样,了解文件权限只是故事的一半,因为当前的用户,组和进程决定了这些权限的应用方式。
可能发生的一些极端情况是:
因此,您编写的任何内容都可能产生误报或误报。
您不添加任何内容的方法是一个很好的简单测试。解决某些问题可能会变得更加复杂,但是在某些情况下,答案总是不是您想要的。
例如,如果您不喜欢在实际写入之前创建文件,请测试该文件是否首先存在:
bool isWritable;
final f = File(filename);
if (f.existsSync()) {
try {
// try appending nothing
f.writeAsStringSync('', mode: FileMode.APPEND, flush: true);
isWritable = true;
} on FileSystemException {
isWritable = false;
}
} else {
isWritable = ???; // do you prefer false positive or false negative
// check if the parent directory exists?
}
// isWritable now, but might not be by the time writing happens
或在测试后将其删除:
bool isWritable;
final f = File(filename);
final didExist = f.existsSync();
try {
// try appending nothing
f.writeAsStringSync('', mode: FileMode.APPEND, flush: true);
isWritable = true;
if (didExist) {
f.deleteSync();
}
} on FileSystemException {
isWritable = false;
}
// isWritable now, but might not be by the time writing happens
Dart使用异步代码引入了额外的复杂性。
如果使用openWrite
方法。它会打开一个流,因此打开文件时不会引发任何写入文件的问题。它们稍后会在使用流或关闭流时发生,这可能与您希望检测到的文件打开代码相距很远。或更糟糕的是,它发生在另一个区域,无法被捕获。
一个有用的技巧是将其打开两次。第一个用于检测文件在关闭时是否可写。第二个是获取将用于写入的流。
try {
final f = File(filename);
f.parent.createSync(recursive: true); // create parent(s) if they don't exist
final tmp = f.openWrite(mode: FileMode.append);
await tmp.flush();
await tmp.close(); // errors from opening will be thrown at this point
// Open it again
sinkForWritingToTheFile = f.openWrite(mode: FileMode.append);
} on FileSystemException catch (e) {
// exception from `close` will be caught here
// exception from the second `openWrite` cannot be caught here
...
}