Прочитайте файл дважды из папки и получите "Процесс не может получить доступ к файлу, потому что он используется другим процессом"

У меня есть простой класс, который подключен к папке, и я хочу удалить все обычные файлы, которые создаются, но когда я читаю файл с тем же именем (один и тот же файл вставляется в папку более одного или двух раз), я получаю ошибка

Exception in thread "main" java.lang.RuntimeException: java.nio.file.FileSystemException: c:\Temp\reader\msg.xml: The process cannot access the file because it is being used by another process.

    at com.project.test.Reader.lambda$0(Reader.java:38)
    at com.project.test.Reader$$Lambda$1/1418481495.accept(Unknown Source)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
    at com.project.test.Reader.main(Reader.java:28)
Caused by: java.nio.file.FileSystemException: c:\Temp\reader\msg.xml: The process cannot access the file because it is being used by another process.

    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
    at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
    at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
    at java.nio.file.Files.delete(Files.java:1126)
    at com.project.test.Reader.lambda$0(Reader.java:35)
    ... 4 more

Вот мой класс читателя:

package com.project.test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

public class Reader {

    public static void main(String[] args) {
        Path path = Paths.get("c:\\Temp\\reader\\");
        WatchService watchService;

        try {
            watchService = path.getFileSystem().newWatchService();
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
            WatchKey watchKey = null;
            while (true) {
                watchKey = watchService.poll(5, TimeUnit.SECONDS);
                if (watchKey != null) {
                    try(Stream<WatchEvent<?>> events = watchKey.pollEvents().stream()) {
                        events.forEach(event -> {
                            if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
                                @SuppressWarnings("unchecked")
                                Path name = ((WatchEvent<Path>) event).context();
                                Path file = path.resolve(name);
                                try {
                                    if (Files.isRegularFile(file)) {
                                        Files.delete(file);
                                    }
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        });
                    }
                    watchKey.reset();
                }
            }
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}

Разве вы не знаете, что не так? Я ожидаю, что должно пропустить некоторое "закрытие" в файле, но путь является только целью для файла и не должен быть закрыт, не так ли? Спасибо за все советы.

1 ответ

Если вы читаете javadoc для WatchService, он говорит, что реализация зависит от операционной системы, т.е. для некоторых операционных систем при добавлении файла в папку может быть создано более одного события:

Например, когда файл в наблюдаемом каталоге изменяется, это может привести к одному событию ENTRY_MODIFY в некоторых реализациях, но к нескольким событиям в других реализациях.

Я догадываюсь, что это происходит и в твоем случае.

Вот некоторые похожие обсуждения:

Java 7 WatchService - игнорирование нескольких вхождений одного и того же события

Служба наблюдения Java NIO создала и ENTRY_CREATE, и ENTRY_MODIFY, когда новый файл добавляется в папку наблюдения

Что бы я сделал, чтобы это работало, - это сохранить путь к файлу, который я собираюсь удалить, в параллельном наборе и попытаться удалить его, только если текущий путь еще не находится в этом наборе.

Другие вопросы по тегам