hello_world_infinity
hello_world_infinity

Reputation: 4830

Check if file is already open

I need to write a custom batch File renamer. I've got the bulk of it done except I can't figure out how to check if a file is already open. I'm just using the java.io.File package and there is a canWrite() method but that doesn't seem to test if the file is in use by another program. Any ideas on how I can make this work?

Upvotes: 58

Views: 123125

Answers (9)

VM Ephex
VM Ephex

Reputation: 1

Just use a try and catch block, and upon catching an exception, use the getMessage() method and check if it contains(“used by another process”)

I added a good bit of extra checks/examples, but otherwise it’s fairly short and straight to the point, it’s probably the best NATIVE and most cross-compatible method. You’re looking at about 8 extra lines of code minimum, not including extra variable declarations, assignments, and block comments, etc.

A bare-bones version:

try {
    //execute
} catch(IOException e) {
    if (e.getMessage().contains(“used by another process”)) {
        System.out.println(“File in use!”);
        return;
    }
    e.printStackTrace();
}

Example usage with more safety checks and potential design:

boolean fileInUse = Boolean.FALSE;
//boolean queueFile = Boolean.FALSE;
try {
    if (fileInUse) { //&& !queueFile
        //queueFile = Boolean.TRUE;
        //could even make queueFile a File object, that is null when not in use, but declared as the File where appropriate when needed in queue.
        return;
    }
    //execute
} catch(IOException e) {
    if (e.getMessage().contains(“used by another process”)) {
        System.out.println(“File in use!”);
        fileInUse = Boolean.TRUE;
        //possible to design a queue, re attempt when file is no longer in use.
        //queueFile = Boolean.TRUE;
        return;
    }
    e.printStackTrace();
}
fileInUse = Boolean.FALSE;
//queueFile = Boolean.FALSE;

Upvotes: -1

siddhartino
siddhartino

Reputation: 359

On Windows I found the answer https://stackoverflow.com/a/13706972/3014879 using

fileIsLocked = !file.renameTo(file)

most useful, as it avoids false positives when processing write protected (or readonly) files.

Upvotes: 10

Stephen C
Stephen C

Reputation: 718768

(The Q&A is about how to deal with Windows "open file" locks ... not how implement this kind of locking portably.)

This whole issue is fraught with portability issues and race conditions:

  • You could try to use FileLock, but it is not necessarily supported for your OS and/or filesystem.
  • It appears that on Windows you may be unable to use FileLock if another application has opened the file in a particular way.
  • Even if you did manage to use FileLock or something else, you've still got the problem that something may come in and open the file between you testing the file and doing the rename.

A simpler though non-portable solution is to just try the rename (or whatever it is you are trying to do) and diagnose the return value and / or any Java exceptions that arise due to opened files.

Notes:

  1. If you use the Files API instead of the File API you will get more information in the event of a failure.

  2. On systems (e.g. Linux) where you are allowed to rename a locked or open file, you won't get any failure result or exceptions. The operation will just succeed. However, on such systems you generally don't need to worry if a file is already open, since the OS doesn't lock files on open.

Upvotes: 13

Dan Ortega
Dan Ortega

Reputation: 1899

Hi I really hope this helps.

I tried all the options before and none really work on Windows. The only think that helped me accomplish this was trying to move the file. Event to the same place under an ATOMIC_MOVE. If the file is being written by another program or Java thread, this definitely will produce an Exception.

 try{

      Files.move(Paths.get(currentFile.getPath()), 
               Paths.get(currentFile.getPath()), StandardCopyOption.ATOMIC_MOVE);

      // DO YOUR STUFF HERE SINCE IT IS NOT BEING WRITTEN BY ANOTHER PROGRAM

 } catch (Exception e){

      // DO NOT WRITE THEN SINCE THE FILE IS BEING WRITTEN BY ANOTHER PROGRAM

 }

Upvotes: 2

Ali
Ali

Reputation: 71

org.apache.commons.io.FileUtils.touch(yourFile) doesn't check if your file is open or not. Instead, it changes the timestamp of the file to the current time.

I used IOException and it works just fine:

try 
{
  String filePath = "C:\sheet.xlsx";
  FileWriter fw = new FileWriter(filePath );                
}
catch (IOException e)
{
    System.out.println("File is open");
}

Upvotes: 4

Aikerima
Aikerima

Reputation: 9

If file is in use FileOutputStream fileOutputStream = new FileOutputStream(file); returns java.io.FileNotFoundException with 'The process cannot access the file because it is being used by another process' in the exception message.

Upvotes: -4

Ahmed Adel Ismail
Ahmed Adel Ismail

Reputation: 2184

    //  TO CHECK WHETHER A FILE IS OPENED 
    //  OR NOT (not for .txt files)

    //  the file we want to check
    String fileName = "C:\\Text.xlsx";
    File file = new File(fileName);

    // try to rename the file with the same name
    File sameFileName = new File(fileName);

    if(file.renameTo(sameFileName)){
        // if the file is renamed
        System.out.println("file is closed");    
    }else{
        // if the file didnt accept the renaming operation
        System.out.println("file is opened");
    }

Upvotes: 11

JavaMachine31
JavaMachine31

Reputation: 265

Using the Apache Commons IO library...

boolean isFileUnlocked = false;
try {
    org.apache.commons.io.FileUtils.touch(yourFile);
    isFileUnlocked = true;
} catch (IOException e) {
    isFileUnlocked = false;
}

if(isFileUnlocked){
    // Do stuff you need to do with a file that is NOT locked.
} else {
    // Do stuff you need to do with a file that IS locked
}

Upvotes: 24

skaffman
skaffman

Reputation: 403461

I don't think you'll ever get a definitive solution for this, the operating system isn't necessarily going to tell you if the file is open or not.

You might get some mileage out of java.nio.channels.FileLock, although the javadoc is loaded with caveats.

Upvotes: 1

Related Questions