2014-04-09 10 views
5

Próbowałem skopiować & wkleić bardzo mały plik do folderu obserwowanego przez usługę oglądania. Po raz pierwszy działa świetnie, ale na wszystkich następnych kopiach & otrzymuję wyjątek, że inny proces obsługuje już plik. Eksperymenty wykazały, że moja usługa jest informowana, gdy system Windows tworzy plik, a nie kiedy jego zawartość jest kopiowana. Jeśli zablokuję plik, system Windows nie będzie mógł skopiować żadnych danych, a plik jest pusty. Z drugiej strony, jeśli przeniesię plik do katalogu, wszystko działa poprawnie.Java: WatchService zostaje poinformowany przed skopiowaniem zawartości

Czy to błąd z systemu Windows? Nie mogłem go przetestować na stacji roboczej Mac lub Linux. A może po prostu nie byłem w stanie tego zrobić. Każda pomoc jest doceniana.

Mój kod wygląda następująco:

try (WatchService watchService = importPath.getFileSystem().newWatchService()) { 
    importPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); 
    handleExistingFiles(); 

    try { 
    do { 
     WatchKey watchKey = watchService.take(); 
     if (!watchKey.isValid()) { 
     continue; 
     } 

     boolean hasCreationEvents = false; 
     for (WatchEvent<?> event : watchKey.pollEvents()) { 
     hasCreationEvents |= event.kind().equals(StandardWatchEventKinds.ENTRY_CREATE); 
     } 
     watchKey.reset(); 

     if (hasCreationEvents) { 
     handleNewFiles(); 
     } 
    } 
    while (!Thread.currentThread().isInterrupted()); 
    } 
    catch (InterruptedException ignoredEx) { 
    Thread.currentThread().interrupt(); 
    } 
} 
+0

Co program (y) tworzy plik, który oglądasz? Nie zapominaj, że często programy piszą do pliku tymczasowego i tylko wtedy nadpisują oryginalny – fge

+0

jego starszy program, który tworzy plik wyjściowy do przesyłania danych do bieżącego. Sprawdzę, jak plik zostanie zapisany, ale jak wspomniał Oleg, może to być problem, że występują dwa zdarzenia, jeden dla stworzenia i jeden dla modyfikacji, a ja odpowiedziałem na zły ... – Teazl

Odpowiedz

6

operacja Kopia nie zawsze jest atomowy.

Z kopią atomową (lub przeniesieniem) otrzymasz jedno zdarzenie ENTRY_CREATE, a plik przywoływany przez zdarzenie będzie kompletny i będzie dostępny do odczytu.

Jeśli kopia nie jest atomowa, po utworzeniu pliku otrzymasz zdarzenie ENTRY_CREATE, a następnie otrzymasz jedno lub więcej zdarzeń ENTRY_MODIFY, gdy plik jest zapisywany przez operację kopiowania.

Nie ma łatwego sposobu określenia, kiedy operacja kopiowania zakończyła zapisywanie w pliku i zwolniła go. W zależności od systemu operacyjnego i systemu plików można uzyskać wyjątek FileNotFoundException podczas próby otwarcia pliku do odczytu, gdy jest on zablokowany przez operację kopiowania lub można pomyślnie otworzyć plik, ale otrzymasz częściową zawartość, gdy faktycznie go odczytasz.

Będziesz musiał zaimplementować heurystyki, takie jak próba odczytania pliku zaraz po ENTRY_CREATE i zmiana harmonogramu odczytu na później, jeśli początkowy odczyt się nie powiódł.

+0

Dzięki za podpowiedź . Zmieniłem kod z ENTRY_CREATE na ENTRY_MODIFY i nie widziałem żadnych problemów, przynajmniej z oknami. Sprawdzę to z innymi systemami operacyjnymi i mam nadzieję, że to też zadziała. Po przetworzeniu pliku zostanie on mimo to usunięty. Zgaduję, że to wystarczy :) – Teazl

+0

Udało mi się przetestować to na systemie MAC. To też działa. Wielkie dzięki! * tak * – Teazl

Powiązane problemy