2012-10-02 56 views
5

我有Java代碼執行以下操作:java.nio.file.Files.isWriteable不java.io.File.canWrite()同意

  1. 創建ZIP擴展使用File.createTempFile()臨時空文件
  2. File.delete()刪除它(我們需要的只是它來生成臨時文件名)採用了全新的OutputSupplier
  3. 複製「模板」 ZIP文件相同的路徑與com.google.commons.io.ByteStreams.copy()給出了相同的文件名
  4. 修改ZIP歸檔(刪除直接ORY)使用TrueZIP 7.4.3

在一個特定的系統中,步驟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檢查相同的文件會返回完全相同的時間(使用調試器),它顯示那它是可寫的

下面是你在調試器中的表達式列表,請參閱:使用JDK 04年7月1日

任何想法

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 

+0

我會嘗試Java 7更新7,看看它是否已修復一個錯誤。 –

+0

我會避免使用這兩個API,而是依賴例如拋出的異常。 '新的FileOutputStream()'。 – EJP

+0

我不會使用java 7,以 – njzk2

回答

3

我會避免使用這兩個API,而是依賴例如拋出的異常。 new FileOutputStream()。他們至少是真實的,並且是真正關心的。使用你提到的API是完全沒有意義的,它引入了時間窗口和重複代碼。無論如何,你必須趕上IOException:爲什麼要寫所有的代碼兩次?

+0

這可能是事實,但你的回答並不能解釋爲什麼這兩個在這種情況下給出了不同的結果。 (參見標題) – Puce

+0

該測試實際上是TrueZIP代碼的一部分,無法避免,因爲根據結果,您可能被允許寫入虛擬文件系統或不寫入。 –

+1

@Puce有時問題的答案是以另一種方式來做。 – EJP

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不被修復。事實證明這是幸運的,因爲在某些情況下,即使您可以毫無問題地打開文件,它仍然可能返回錯誤。

真的,我會總結這樣的方法:當你無法真正寫入文件

  • File.canWrite有時返回true。
  • 當您實際寫入文件時,Files.isWriteable有時會返回false。

我不知道現在哪種方法的要點。因爲每個使用這些文件的人最終都必須編寫一個實際上試圖打開該文件的未損壞的對等文件,所以人們想知道他們爲什麼不打開文件來自己執行檢查。

+0

由於https://bugs.openjdk.java.net/browse/JDK-7190897 Files.isWritable按預期工作。 –

+0

我認爲簡單地執行操作,而不是檢查然後執行操作仍然是可取的,因爲Files.isWritable的結果立即過時,即使它是_was_正確的。 isReadable,exists,notExists,isRegularFile,isDirectory,isSymbolicLink也可能更多。 – Trejkaz

5

windows下的java.nio.file.Files.isWritable存在一個錯誤: 它不會考慮隱式權限。 java bug #7190897

+3

更新:此錯誤在Java 8(b84)中得到修復,並被移植到Java 7u40。 –