如果我想安全地尝试在D中打开文件,那么这是
的首选方式我猜测第二种替代结果会产生更多IO并且更复杂吗?
答案 0 :(得分:6)
如果根据正常的程序操作和给定的用户输入预期文件在那里,那么使用1 - 只是尝试打开文件并依赖异常处理来处理文件不存在的异常情况。 / p>
例如:
/// If the user has a local configuration file in his home directory, open that.
/// Otherwise, open the global configuration file that is a part of the program,
/// and should be installed on all systems where the program is running.
File configFile;
if ("~/.transmogrifier.conf".expandTilde.exists)
configFile.open("~/.transmogrifier.conf".expandTilde);
else
configFile.open("/etc/transmogrifier.conf");
请注意,使用2可能会导致程序出现安全问题。例如,如果文件在程序检查文件是否存在时出现,但在尝试打开文件时消失,则程序可能会以意外的方式运行。如果您使用2,请确保程序在打开文件失败时仍然以理想的方式运行,即使您的程序刚检查该文件是否存在且可读。
答案 1 :(得分:4)
通常,最好先检查文件是否存在,因为文件通常很可能不存在,并且只是在尝试打开文件时让它失败是使用异常进行流量控制的情况。在文件不存在的情况下效率也很低,因为D中的异常非常昂贵(尽管I / O的成本可能仍然超过了I / O的成本)是)。
在可能引发异常的情况下,通常认为使用异常是不好的做法。在这些情况下,返回操作是否成功或在尝试操作之前检查操作是否可能成功要好得多。在打开文件的情况下,您可能会执行后者。所以,做你想做的事最干净的方法就是做一些像
这样的事情if(filename.exists)
{
auto file = File(filename);
...
}
或者如果您想一次性以字符串形式阅读整个文件,那么
if(filename.exists)
{
auto fileContents = readText(filename);
...
}
exists
和readText
位于std.file中,File
位于std.stdio中。
如果您正在处理文件很可能存在且因此不太可能抛出异常的情况,那么就跳过检查并尝试打开文件很好。但是你想要避免的是依赖于当 不太可能导致操作失败时抛出的异常。您希望很少抛出异常,因此在尝试操作之前检查操作是否成功,如果它们可能会失败并抛出异常。否则,您最终会使用流量控制异常并损害程序的效率(和可维护性)。
通常情况下,当您尝试打开文件时,文件不会存在,因此通常情况下您应该在尝试打开之前检查文件是否存在它(但它最终取决于您的特定用例)。
答案 2 :(得分:4)
我会说你需要做好准备才能抛出异常,否则你就会遇到竞争条件(另一个进程可能会删除测试和open之间的文件等)。因此,最好只是继续开放,然后处理意外情况。