java.nio.file.Files.isWriteable与java.io.File.canWrite()不一致

时间:2012-10-02 10:04:11

标签: java nio temporary-files truezip writable

我有Java代码执行以下操作:

  1. 使用File.createTempFile()
  2. 创建一个包含ZIP扩展名的临时空文件
  3. 使用File.delete()删除它(我们真的只希望它生成临时文件名)
  4. 将“模板”ZIP文件复制到com.google.commons.io.ByteStreams.copy()的同一路径,使用相同文件名的新OutputSupplier
  5. 使用TrueZIP 7.4.3修改ZIP存档(删除目录)
  6. 在特定系统上,第4步与FsReadOnlyArchiveFileSystemException - "This is a read-only archive file system!"一致失败(请参阅http://java.net/projects/truezip/lists/users/archive/2011-05/message/9

    调试TrueZIP代码,我注意到以下内容:

    • 上述任何步骤之间没有打开文件句柄,特别是在步骤4之前
    • 使用File.canWrite()检查同一文件而不是NIO以完全相同的时间(使用调试器)返回,它表明它是可写的

    以下是您在调试器表达式列表中看到的内容:

    fn => "C:/myworkdir/temp/myfile4088293380313057223tmp.zip"
    java.nio.file.Files.isWritable(java.nio.file.Paths.get(fn)) => false
    new java.io.File(fn).canWrite() => true
    

    使用JDK 1.7.04

    有什么想法吗?

3 个答案:

答案 0 :(得分:6)

Windows下的java.nio.file.Files.isWritable中存在一个错误: 它不会考虑隐式权限。 java bug #7190897

答案 1 :(得分:5)

最终结果并不令人惊讶:

java.nio.file.Files.isWritable(java.nio.file.Paths.get(fn)) => false
new java.io.File(fn).canWrite() => true

File.canWrite根本不关注ACL,只检查MS-DOS只读属性。

Files.isWriteable注意ACL,但无论出于何种原因(为了保持损坏的程序都被破坏?),他们将File.canWrite保留为未修复。事实证明这很幸运,因为在某些情况下,即使您可以毫无问题地打开文件,它似乎也会返回false。

真的,我会总结一下这样的方法:

  • 当您无法实际写入文件时,File.canWrite有时会返回true。
  • 当您可以实际写入文件时,Files.isWriteable有时会返回false。

我不确定这两种方法的重点是什么。因为使用这些文件的每个人最终必须写一个实际上试图打开文件的非破坏的等价物,所以人们想知道他们为什么不打开文件来自己进行检查。

答案 2 :(得分:3)

我会避免使用这两种API,而是依赖于例如抛出的异常。 new FileOutputStream()。它们至少是真实的,真正令人担忧的。使用你提到的API完全没有意义,它引入了时序窗口和重复的代码。无论如何你必须抓住IOException:为什么要写两次所有代码?