2016-09-22 2 views
3

Ich versuche, eine Datei zu erstellen, und vorher löschen Sie, wenn es existiert. Mein Problem ist, dass, wenn ich einen erfolgreichen Löschvorgang habe und sofort danach versuche, den gleichen Ordner zu erstellen, es mit AccessDenied fehlschlägt. Die Methodenbeschreibung (sowohl für deleteIfExists als auch für createDirectory) erwähnt solch ein Verhalten nicht, also denke ich, dass ich etwas falsch mache.Der Versuch, ein Verzeichnis sofort nach einem erfolgreichen zu erstellen deleteIfExists löst AccessDenied Exception

Dies ist der Code:

package nio2; 
import java.io.*; 
import java.nio.file.*; 
public class Test{ 

    public static void main(String[] args) 
    { 
     Path existing = Paths.get("nio2//alpha//inner.txt"); // already existing 
     Path cpytarget = Paths.get("nio2//alphacpy//inner.txt"); // file to be created 
     Path target = Paths.get("nio2//alphacpy");// 
     try{ 
      if(Files.exists(cpytarget)) 
      { 
       Files.list(target).forEach(Test::WrappedDeleteIfExists); // deleting files inside folder 
       System.out.println("Deleting the directory if it exists - alphaCpy\t" + Files.deleteIfExists(target));//deleting 
      } 
      else 
       System.out.println("It does not exist, no need to delete anything"); 
      System.out.println("Creating alphaCpy\t" + Files.createDirectory(target));//creating 
      System.out.println("copying inner.txt to the new directory\t" + Files.copy(existing,cpytarget)); 
     }catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    public static void WrappedDeleteIfExists(Path in) 
    { 
     try{ 
      System.out.println("Deleting files inside the folder\t" + Files.deleteIfExists(in)); 
     }catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

} 

So in einem erfolgreichen Lauf (wenn kein Lösch ist). dies ist der Ausgang

It does not exist, no need to delete anything 
Creating alphaCpy  nio2\alphacpy 
copying inner.txt to the new directory nio2\alphacpy\inner.txt 

Wenn ich es danach ausgeführt werden, wenn die Ordner und die Datei bereits vorhandenen i die Ausnahme erhalten:

Deleting files inside the folder  true 
Deleting the directory if it exists - alphaCpy true 
java.nio.file.AccessDeniedException: nio2\alphacpy 
     at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83) 
     at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) 
     at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) 
     at sun.nio.fs.WindowsFileSystemProvider.createDirectory(WindowsFileSystemProvider.java:504) 
     at java.nio.file.Files.createDirectory(Files.java:674) 
     at nio2.Test.main(Test.java:19) 

nächster Lauf ist wieder erfolgreich, da es bereits gelöscht wurde und bald. Die Frage ist also, was die AccessDenied-Ausnahme verursacht? Bedenken Sie, dass die Datei nicht geöffnet/verwendet wird und die relativen Pfade gültig sind.

EDIT: Ok ich schaffte es zu korrigieren, aber ehrlich gesagt kann ich mir immer noch nicht das ursprüngliche Problem erklären. Also werde ich dankbar sein, wenn jemand damit helfen kann. Ich ging von der Verwendung eines Streams zu Datei [], um die Datei in dem Ordner zu löschen. Nachdem ich das gemacht habe, funktioniert es wie ein Zauber. Hier

ist der korrigierte Code:

public static void main(String[] args) throws InterruptedException 
    { 
     Path existing = Paths.get("E:/work/Java/Tests/alpha/inner.txt"); // already existing 
     Path cpytarget = Paths.get("E:/work/Java/Tests/alphacpy/inner.txt"); // file to be created 
     Path target = Paths.get("E:/work/Java/Tests/alphacpy");// 
     File fileTarget = new File("E:/work/Java/Tests/alphacpy");  
     try{ 
      if(Files.exists(cpytarget)) 
      { 
       WrappedDeleteIfExists(fileTarget.listFiles()); // CHANGED , no longer using Stream<Path> pipeline to go through the file list 
       // deleting files inside folder 
       System.out.println("Deleting the directory if it exists - alphaCpy\t" + Files.deleteIfExists(target));//deleting 
      } 
      else 
       System.out.println("It does not exist, no need to delete anything"); 
      System.out.println(Files.exists(target)); 

      System.out.println("Creating alphaCpy\t" + Files.createDirectory(target));//creating 
      System.out.println("copying inner.txt to the new directory\t" + Files.copy(existing,cpytarget)); 
     }catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    // CHANGED - using File[] instead of Path 
    public static void WrappedDeleteIfExists(File[] in) 
    { 
     for(int i =0;i<in.length;i++) 
     { 
      System.out.println("Deleting files inside the folder\t" +in[i].delete()); 
     } 

    } 

Offensichtlich sind die Stream-Operationen halten sie gesperrt irgendwie, auch nach Abschluss, aber dies ist kein IO-Stream (oder ist es mit files.list() ??) dass ich schließen kann, also was kann ich tun, um es mit Stream arbeiten zu lassen - es ist nicht etwas, das verschließbar ist oder etwas, das versucht GC zu erzwingen, macht Sinn.

+0

Wenn Sie durch den Code eine Zeile nach dem anderen in Ihrem Debugger sehen Sie immer noch den gleichen Fehler? Wenn dies nicht der Fall ist, kann die Löschoperation zurückkehren, sobald das Löschen vom Betriebssystem akzeptiert wird, aber das Betriebssystem benötigt eine endliche Zeit (zehn bis hundert Millisekunden), um das Löschen des Verzeichnisses abzuschließen. Wenn dies der Fall ist, müssen Sie eine Wiederholungsschleife mit exponentiellem Backoff bis etwa 1 Sekunde einfügen. Sie können den Vorgang nicht unbegrenzt wiederholen, da möglicherweise eine Bedingung für den Zugriff verweigert wurde. –

+0

Gleiches Ergebnis im Debugger Schritt für Schritt. Auch versucht mit dem Hinzufügen von Thread.sleep (5000); , so dass der Haupt-Thread nach dem Löschen einige Sekunden wartet. Keine Änderung der Ergebnisse. –

+1

Warum verwenden Sie doppelte _forward_ Schrägstriche. Du solltest das nicht tun. Versuchen Sie einzelne Schrägstriche. Drucken Sie auch den Wert von 'Files.exists (target)' nach dem Löschvorgang, um zu sehen, was der NIO-Stapel über das Vorhandensein des Verzeichnisses denkt. –

Antwort

0

Ich bemerkte ein ähnliches Problem mit einem Programm, das Files.list (dir), gefolgt von Files.deleteIfExists (Pfad) verwendet. Keiner der gelöschten Ordner verschwand aus der Windows Explorer-Ansicht, bis die VM beendet wurde, und führte zu Zugriffsverweigerung, wenn innerhalb von Windows Explorer auf die Zeit geklickt wurde, zu der die VM beendet wurde.

Mein Programm wurde einfach durch Schließen der Files.list() - Stream nach der Verwendung behoben, am besten mit try (Ressource) ... endlich. Dann Windows Explorer war synchron mit jedem Löschen sofort sie aufgetreten sind, nicht warten, bis die VM beendet wurde

try(Stream<Path> str = Files.list(target)) 
{ 
    // do your str.forEach() calls with Files.deleteIfExists 
} 
finally 
{ 
} 
Verwandte Themen