您可以删除打开的文件吗?
打开文件时删除文件的目录条目是完全有效的。在Unix中,这是默认的语义,并且Windows
FILE_SHARE_DELETE在打开该文件的所有文件句柄上进行设置时的行为类似。
[编辑:感谢@couling的讨论和更正]
但是,两者之间存在细微的差别:Unix 立即 删除文件 名 ,而Windows 仅在关闭最后一个句柄时才删除文件名
。但是,它会阻止您打开具有相同名称的文件,直到关闭(已删除)文件的最后一个句柄为止。
去搞清楚 …
但是,在两个系统上,删除文件并不一定会使文件消失,只要仍然有打开的句柄,它仍会占用磁盘上的空间。仅在最后一个打开的句柄关闭时才释放文件占用的空间。
游览:Windows
在Windows上必须指定该标志,这使大多数人似乎Windows无法删除打开的文件,但实际上并非如此。这只是 默认 行为。
CreateFile():
在文件或设备上启用后续打开操作以请求删除访问。
否则,如果其他进程请求删除访问,则它们将无法打开文件或设备。
如果未指定此标志,但是已打开文件或设备以进行删除访问,则该功能将失败。注意删除访问权限允许删除和重命名操作。
DeleteFile():
DeleteFile函数在关闭时将文件标记为要删除。因此,在关闭文件的最后一个句柄之前,不会发生文件删除。随后调用CreateFile打开文件失败,并显示ERROR_ACCESS_DENIED。
打开没有名称的文件的句柄是创建未命名临时文件的最典型方法之一:创建一个新文件,打开它,然后删除该文件。现在,您可以处理其他人无法打开的文件。在Unix上,文件名确实消失了,在Windows上,您无法打开具有相同名称的文件。
现在的问题是:
是否
设置Files.newOutputStream()FILE_SHARE_DELETE
?
查看源代码,您可以看到
shareDelete确实默认为
true。重置它的唯一方法是使用非标准
ExtendedOpenOption
NOSHARE_DELETE。
因此,是的,您可以删除Java中打开的文件,除非它们被明确锁定。
为什么不能重新创建已删除的文件?
DeleteFile()上面的文档中隐藏了答案:该文件仅标记为删除,该文件仍然存在。在Windows上,只有 正确
删除文件(即关闭文件的所有句柄)后,才能使用标记为删除的文件 名 创建文件。 __
Windows混用名称删除和实际文件删除的可能混淆可能是Windows首先不允许默认情况下删除打开文件的原因。
为什么要Files.exists()
退货false
?
Files.exists()在Windows的最深层中
,“某个时刻”会打开该文件,我们已经知道我们无法在Windows上重新打开已删除但仍打开的文件 。
详细来说:Java代码调用
FileSystemProvider.checkAccess())不带参数,该调用
WindowsFileSystemProvider.checkReadAccess()立即尝试打开文件,因此失败。据我所知,这是您致电时采取的路径
Files.exist()。
还有另一个代码路径调用
GetFileAttributeEx()来检索文件属性。再次没有记载,当您尝试检索
已删除但尚未删除的 文件的属性时会发生什么,但是实际上,您无法检索 标记为删除 的文件的文件属性。
猜猜,我会说在某个时候
GetFileAttributeEx()调用
GetFileInformationByHandle(),它将永远不会到达,因为它首先无法获得文件句柄。
确实如此,在
DeleteFile()文件出于大多数实际目的而消失之后。它仍然有一个名称,但是会显示在目录列表中,并且在原始文件的所有句柄都关闭之前,您无法打开具有相同名称的文件。
这种行为或多或少是一致的,因为
GetFileAttributes()用于检查文件是否存在实际上是 文件可访问性 检查,它被解释为 文件存在
。
FindFirstFile()(由Windows资源管理器用于确定文件列表)查找文件
名, 但不告诉您有关文件 名的 可访问 性。
欢迎您再来几个怪异的循环。



