6

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

  1. 使用创建一个带有 ZIP 扩展名的临时空文件File.createTempFile()
  2. 删除它File.delete()(我们只希望它生成一个临时文件名)
  3. com.google.commons.io.ByteStreams.copy()使用OutputSupplier给定相同文件名的新文件将“模板”ZIP 文件复制到相同路径
  4. 使用 TrueZIP 7.4.3 修改 ZIP 存档(删除目录)

在特定系统上,第 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

有任何想法吗?

4

3 回答 3

6

windows下java.nio.file.Files.isWritable有个bug:不考虑隐式权限。 Java 错误 #7190897

于 2013-07-10T12:49:12.880 回答
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。

我不确定现在这两种方法的意义是什么。由于使用这些的每个人最终都必须编写一个完整的等效文件来实际尝试打开文件,因此人们想知道为什么他们不只是打开文件来自己进行检查。

于 2013-02-20T05:08:04.773 回答
5

我会避免同时使用这两种 API,而是依赖 eg 抛出的异常new FileOutputStream()。它们至少是真实的,并且是真正值得关注的。使用您提到的 API 完全没有意义,它会引入时间窗口和重复代码。无论如何,你必须抓住IOException:为什么要把所有的代码写两次?

于 2012-10-02T10:21:17.487 回答