javafilenotfoundexceptionwatchservice

FileNotFound exception even though file is in the place during watch service in java


I have a watch service running on a folder, when I am trying to modify and existing file using evenKind == Modify (basically pasting a same file without removing the current file) I am getting FileNotFoundException (The process cannot access the file because it is being used by another process.)

if (eventKind == StandardWatchEventKinds.ENTRY_MODIFY) {
                
                String newFileChecksum = null;
                
                if (eventPath.toFile().exists()) {
                    newFileChecksum = getFileChecksum(eventPath.toFile());

                }
                        
                if (fileMapper.containsKey(eventPath)) {
                    String existingFileChecksum = fileMapper.get(eventPath);


                if (!existingFileChecksum.equals(newFileChecksum)) {

                        fileMapper.replace(eventPath, existingFileChecksum, newFileChecksum);
                        
                        log.info("listener.filemodified IN");
                        for (DirectoryListener listener : this.listeners) {
                            
                            listener.fileModified(this, eventPath);
                        }
                        log.info("listener.filemodified OUT");
                    } else {
                        log.info("existing checksum");
                        log.debug(String.format(
                                "Checksum for file [%s] has not changed. Skipping plugin processing.",
                                eventPath.getFileName()));
                    }
         
                }
    
            }

In the code when...getFileChecksum() is called

if (eventPath.toFile().exists()) {

        newFileChecksum = getFileChecksum(eventPath.toFile());

}

So ideally, eventPath.toFile().exists() is TRUE, hence code is going inside if but when getFileChecksum() is called, it goes to method...

private synchronized String getFileChecksum(File file) throws IOException, NoSuchAlgorithmException {
        
        MessageDigest md5Digest = MessageDigest.getInstance("MD5");
        
        FileInputStream fis = null;
        
        if(file.exists()) {
            
            try {
                fis = new FileInputStream(file);
            } catch(Exception e) {
                e.printStackTrace();
            }
        } else {
            log.warn("File not detected.");
        }
         
        byte[] byteArray = new byte[1024];
        
        int bytesCount = 0; 
     
        while ((bytesCount = fis.read(byteArray)) != -1) {
            
            md5Digest.update(byteArray, 0, bytesCount);
        };
 
        fis.close();
        
        byte[] bytes = md5Digest.digest();
       
        StringBuilder stringBuilder = new StringBuilder();
        
        for (int i=0; i< bytes.length ;i++) {
            
            stringBuilder.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }
         
       return stringBuilder.toString();
    }
}

An exception is coming fis = new FileInputStream(file); even if the file is present in the folder.

FileNotFoundException (The process cannot access the file because it is being used by another process.)

I created a RandomAccessFile and a channel to release any LOCK placed on file, but it is not working. Please suggest what could be happening here.

//UPDATE --> This is the infinite while loop that I have,

WHAT IS HAPPENING? WHEN I PUT A FILE 1 create and 2 update are getting called, suppose, when I am deleting the file, 1 delete 1 modify is being called, and IF I PUT THE SAME FILE BACK TO FOLDER, I GET CREATE but before CREATE is finishing, MODIFY IS BEING called. and create is not running instead modify is running.

I fixed this issue by putting Thread.sleep(500) between

WatchKey wk = watchService.take();
Thread.sleep(500)
        for (WatchEvent<?> event : wk.pollEvents()) {

But I dont think I can justify use of sleep here. Please help

WatchService watchService = null; WatchKey watchKey = null;

        while (!this.canceled && (watchKey == null)) {

           watchService = watchService == null
                        ? FileSystems.getDefault().newWatchService() : watchService;
                watchKey = this.directory.register(watchService,
                        StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE,
                        StandardWatchEventKinds.ENTRY_CREATE);
         }
         while (!this.canceled) {

    try {

        WatchKey wk = watchService.take();
        
        for (WatchEvent<?> event : wk.pollEvents()) {

            Kind<?> eventKind = event.kind();
            
            System.out.println("Event kind : " + eventKind);

            Path dir = (Path)wk.watchable();
            Path eventPath = (Path) event.context();

            Path fullPath = dir.resolve(eventPath);
            fireEvent(eventKind, fullPath);
        }

        wk.reset();

    }

Solution

  • I have a better approach, use and a while loop on a var isFileReady like this...

    var isFileReady = false;
    
    while(!isFile...) {
    }
    

    inside while create a try and catch.

    try {
    
    FileInputStream fis = new FileInputStream();
    
    isFileReady = true;
    } catch () {
    catch exception or print file not ready.
    }
    

    This will solve your problem.