Java 7 WatchService - The process cannot access the file because it is being used by another process

10,402

Solution 1

Ok, I found a solution. I don't know if it is the best way to do this, but it works. Unfortunately, file.canRead() and file.canWrite() both return true, even if the file still locked by Windows. So I discovered that if I try to "rename" it with the same name, I know if Windows is working on it or not. So this is what I did:

    while(!sourceFile.renameTo(sourceFile)) {
        // Cannot read from file, windows still working on it.
        Thread.sleep(10);
    }

Solution 2

Solution given by Arundev worked for me.

I needed to add sleep time otherwise it wouldn't work for multiple requests and used to get the error "The process cannot access the file because it is being used by another process"

if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

// now do your intended jobs ... 

Solution 3

I had the similar problem. But my file isn't being locked when it's being copied . If I had been trying to read it right after I had got created event that It was empty.

I think in your case there are no need tricks and you can simply handle error and if you get error than you can execute sleep and try again after that. But for me it's not right for me. I don't get error. So I tried your soloution and I understood that it isn't acceptable for me too because I don't have rights except reading. So I can suggest my 'trick'. I'm using class java.io.RandomAccessFile:

List<String> lines = null;

while(true){
    try( RandomAccessFile raf = new RandomAccessFile( fileFullPath.toFile() , "r" ) ){
        lines = Files.readAllLines( fileFullPath , Charset.forName(ENCODING) );
        break;
    }catch(FileNotFoundException ex){
        LOG.warn("File isn't yet completed: {}",ex.getMessage() );
        LOG.info( "Waiting {} for next attempt to read it" , SLEEP_INTERVAL_READING );
        try {
            Thread.sleep(SLEEP_INTERVAL_READING);
        } catch (InterruptedException e) {
            LOG.error("Waiting was interrupted",e);
        }
    }catch(Exception ex){
        LOG.error("Error in reading file ",ex);
        clear();
        return false;
    }
} 
Share:
10,402
jfajunior
Author by

jfajunior

Updated on June 27, 2022

Comments

  • jfajunior
    jfajunior almost 2 years

    I followed the Watching a Directory for Changes Java7 nio2 tutorial to recursively monitor the entire contents of a directory using the code sample WatchDir.java.

    The code looks like this:

    // Get list of events for the watch key.
    for (WatchEvent<?> event : key.pollEvents()) {
    // This key is registered only for ENTRY_CREATE events, but an OVERFLOW event 
    // can occur regardless if events are lost or discarded.
    if (event.kind() == OVERFLOW) {
        continue;
    }
    
    // Context for directory entry event is the file name of entry.
    @SuppressWarnings("unchecked")
    WatchEvent<Path> ev = (WatchEvent<Path>)event;
    Path fileName = ev.context();
    Path fullPath = dir.resolve(fileName);
    
    try {
        // Print out event.
        System.out.print("Processing file: " + fileName);
    
        processed = fileProcessor.processFile(fullPath);
    
        System.out.println("Processed = " + processed);
    
        if (processed) {
            // Print out event.
            System.out.println(" - Done!");
        }
    } 
    catch (FileNotFoundException e) {
        System.err.println("Error message: " + e.getMessage());
    }
    catch (IOException e) {
        System.err.println("Error processing file: " + fileName.toString());
        System.err.println("Error message: " + e.getMessage());
    }
    

    Ok, so the problem (where I am sure doing something stupid) is here:

    processed = fileProcessor.processFile(fullPath);
    

    And what it does is something like this:

    public synchronized boolean processFile(Path fullPath) throws IOException {
    String line;
    String[] tokens;
    String fileName = fullPath.getFileName().toString();
    String fullPathFileName = fullPath.toString();
    
    // Create the file.
    File sourceFile = new File(fullPath.toString());
    
    // If the file does not exist, print out an error message and return.
    if (sourceFile.exists() == false) {
        System.err.println("ERROR: " + fullPathFileName + ": No such file");
        return false;
    }
    
    // Check file extension.
    if (!getFileExtension(fullPathFileName).equalsIgnoreCase("dat")) {
        System.out.println(" - Ignored.");
        return false;
    }
    
    // Process source file.
    try (BufferedReader bReader = new BufferedReader(new FileReader(sourceFile))) {
        int type;
    
        // Process each line of the file.
        while (bReader.ready()) {
    
            // Get a single line.
            line = bReader.readLine();
    
            // Get line tokens.
            tokens = line.split(delimiter);
    
            // Get type.
            type = Integer.parseInt(tokens[0]);
    
            switch (type) {
            // Type 1 = Salesman.
            case 1:
                -> Call static method to process tokes.
                break;
            // Type 2 = Customer.
            case 2:
                -> Call static method to process tokes.
                break;
            // Type 3 = Sales.
            case 3:
                -> Call static method to process tokes.
                break;
            // Other types are unknown!
            default:
                System.err.println("Unknown type: " + type);
                break;
            }
        }
    
        PrintStream ps = null;
        try {
    
            // Write output file.
            // Doesn't matter. 
    
        } 
        finally {               
            if (ps != null) {
                ps.close();
            }
        }
        return true;
    }
    }
    

    The first time I handle an event, it all works fine! Even if there is more than 1 file to process. But in the consecutive times, I get this error message:

    The process cannot access the file because it is being used by another process

    What am I doing wrong here? What can I do to process the consecutive files with sucess?

    Two important notes that I forgot to mention:

    1. I'm using Windows 7.
    2. When I run the application in debug mode, it works.

    EDIT: If I add a sleep before I try to use the file, it works:

    Thread.sleep(500);
    
    // Process source file.
    try (BufferedReader bReader = new BufferedReader(new FileReader(sourceFile))) {
    

    So, is it possible to be Windows that is not unlocking the files in time? How can I fix that (in a proper way)?