2012-10-02 4 views
5

Ho codice Java nel seguente modo:java.nio.file.Files.isWriteable non è d'accordo con java.io.File.canWrite()

  1. Creare un file vuoto temporaneo con estensione ZIP utilizzando File.createTempFile()
  2. Cancellare con File.delete() (abbiamo solo voluto che generare un nome file temporaneo)
  3. Copiare un "modello" file ZIP per lo stesso percorso con com.google.commons.io.ByteStreams.copy() utilizzando un nuovo OutputSupplier dato lo stesso nome del file
  4. Modificare la ZIP archivio (rimuovi un diretto ORY) utilizzando TrueZIP 7.4.3

Su un sistema specifico, il passaggio 4 non riesce coerentemente con FsReadOnlyArchiveFileSystemException - "This is a read-only archive file system!" (vedi http://java.net/projects/truezip/lists/users/archive/2011-05/message/9)

Debug del codice di TrueZIP, ho notato quanto segue:

  • C'è nessun handle di file aperto su questo file tra uno qualsiasi dei passaggi precedenti e in particolare non prima del passaggio 4
  • Controllare lo stesso file con File.canWrite() anziché NIO restituisce allo stesso tempo (usando un debugger), mostra quella è scrivibile

Ecco quello che si vede nella lista di espressioni del debugger:

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 

Utilizzando JDK 1.7.04

Tutte le idee?

+0

Vorrei provare Java 7 update 7 per vedere se è un bug che è stato corretto. –

+0

Eviterei di utilizzare entrambe le API e invece di fare affidamento sulle eccezioni generate da es. 'new FileOutputStream()'. – EJP

+0

non userei java 7, per iniziare con – njzk2

risposta

3

Eviterei di utilizzare entrambe le API e invece di fare affidamento sulle eccezioni generate da es. new FileOutputStream(). Almeno sono reali e di reale preoccupazione. L'utilizzo delle API menzionate è del tutto inutile e introduce finestre temporali e codice ripetuto. Devi prendere lo IOException in ogni caso: perché scrivere tutto quel codice due volte?

+0

Potrebbe essere vero, ma la tua risposta non spiega perché i due danno un risultato diverso in questo caso. (vedi titolo) – Puce

+0

Il test fa parte del codice TrueZIP e non può essere evitato perché, a seconda del risultato, potresti essere autorizzato a scrivere sul file system virtuale o meno. –

+1

@Puce A volte la risposta a una domanda è di farlo in un altro modo. – EJP

5

Il risultato finale non è troppo sorprendente:

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

File.canWrite non presta attenzione alle ACL a tutti e controlla solo il MS-DOS attributo di sola lettura.

Files.isWritable presta attenzione agli ACL ma per qualsiasi motivo (per mantenere i programmi interrotti non funzionanti?) Hanno lasciato File.canWrite non risolto. Questo risulta essere fortunato, perché in alcune situazioni sembra che possa restituire false anche quando è possibile aprire il file senza problemi.

Davvero, vorrei riassumere i metodi come questo:

  • File.canWrite a volte restituisce true quando non si può effettivamente scrivere sul file.
  • Files.isWriteable a volte restituisce false quando è possibile scrivere sul file.

Non sono sicuro di quale sia il punto di entrambi i metodi in questo momento. Dal momento che tutti coloro che li utilizzano, alla fine, devono scrivere un equivalente non-broken che in realtà tenta di aprire il file, ci si chiede perché non hanno semplicemente aperto il file per fare il controllo da soli.

+0

Poiché https://bugs.openjdk.java.net/browse/JDK-7190897 Files.isWritable funziona come previsto. –

+0

Penso che sia comunque consigliabile eseguire semplicemente l'operazione, piuttosto che controllarla e quindi eseguirla, perché il risultato di Files.isWritable è immediatamente scaduto, anche se _was_ correct. Lo stesso vale per isReadable, exists, notExists, isRegularFile, isDirectory, isSymbolicLink e probabilmente più. Aggiornamento – Trejkaz

5

C'è un errore in java.nio.file.Files.isWritable sotto windows: non prenderà in considerazione le autorizzazioni implicite. java bug #7190897

+3

: questo bug è stato corretto in Java 8 (b84) e sostituito a Java 7u40. –