2012-09-07 9 views
6

Gdy katalog monitorowany przez WatchService zostaje usunięty, jego katalog nadrzędny nie od razu odzwierciedla usunięcie w jego metodzie pliku listFiles i nie można go usunąć. Aż cała usługa jest wyraźnie stopped konsekwencje dla rodziców wydają się być:Usługa odtwarzania Java wydaje się odtworzyć usunięte pliki. Co się dzieje?

  1. recommended recursive solution usuwania niepusty rygorem katalogów.
  2. deleteOnExit nieprowadzenie przy normalnym wypowiedzeniu
  3. Połączenia z delete zwracające wartość false i nie mające wpływu na system plików.

Aby wykazać, ten kod testowy:

import java.io.*; 
import java.nio.file.*; 

class DirectoryTester { 
    static WatchService watcher; 
    static { 
    try{watcher = FileSystems.getDefault().newWatchService();} 
    catch (IOException e) {e.printStackTrace();} 
    } 

    public static void main(String[] args) throws IOException { 
    String SEPARATE = System.getProperty("file.separator"); 
    String testDirName = System.getProperty("user.dir") + SEPARATE + "testDir"; 
    String subDirName = testDirName + SEPARATE + "subDir"; 
    String fileName = subDirName + SEPARATE +"aFile"; 
    create(fileName); 
    Paths.get(subDirName).register(watcher, StandardWatchEventKinds.ENTRY_DELETE); 
    delete(new File(testDirName)); 
    } 

    static void create(String nameOfFile) throws IOException { 
    new File(nameOfFile).getParentFile().mkdirs(); 
    Files.createFile(Paths.get(nameOfFile)); 
    System.out.println("Created " + nameOfFile); 
    }  

    static void delete(File toDelete) throws IOException { 
    if (toDelete.isDirectory()) 
     for (File c : toDelete.listFiles()) 
     delete(c); 
    int numContainedFiles = toDelete.listFiles() != null ? toDelete.listFiles().length : 0; 
    if (!toDelete.delete()) { 
     System.out.println("Failed to delete " + toDelete + " containing " + numContainedFiles); 
    } 
    else { 
     System.out.println("Deleted " + toDelete + " containing " + numContainedFiles); 
    } 
    } 
} 

daje następujący wynik w systemie Windows, który odpowiada z testDir nie są usunięte w systemie plików.

Created C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir\aFile 
Deleted C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir\aFile containing 0 
Deleted C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir containing 0 
Failed to delete C:\Dropbox\CodeSpace\JavaTestbed\src\testDir containing 1 

Jeśli mogę umieścić punkt przerwania po usunięciu subDir widzę, że rzeczywiście zostało usunięte w systemie plików. Wznowienie z punktu przerwania powoduje, że ostatnie usunięcie się udało, co sugeruje, że może to być problem z widocznością zmian wprowadzonych przez wątek usługi monitorowania. Czy ktoś wie, co się tutaj dzieje i czy jest to błąd? Co faktycznie próbuję zrobić, to usunąć katalogi, które są monitorowane bez zatrzymywania monitorowania w innych katalogach, biorąc pod uwagę, że nie wydaje się, że istnieje metoda wyrejestrowywania ścieżki zapewniona przez API, jakie są inne standardowe metody Java do osiągnięcia tego?

+0

Zastanawiam się, czy jest to tylko problem Windows – Pyrolistical

+1

To samo zachowanie tutaj. Dodanie 'Thread.sleep (100);' w głównym przed wywołaniem 'delete (nowy plik (testDirName));' rozwiązuje problem - dziwne ... – assylias

Odpowiedz

7

prawdopodobnie związane:

http://bugs.sun.com/view_bug.do?bug_id=6972833

WatchService ma otwarte dojście do każdego oglądanego katalogu. Jeśli katalog śledzenia zostanie usunięty, usługa WatchService zamyka uchwyt, aby pozycja katalogu mogła zostać usunięta z katalogu nadrzędnego. Pojawia się problem dla narzędzi i aplikacji, które oczekują możliwości natychmiastowego usunięcia katalogu nadrzędnego, ponieważ może to potrwać kilka milisekund, zanim usługa watch otrzyma powiadomienie i zamknie uchwyt. Jeśli w tym czasie narzędzie spróbuje usunąć katalog nadrzędny, nie powiedzie się. W tej chwili nie mamy rozwiązania tego problemu.

+0

+1 Wydaje się być dokładnie tym. – assylias