how to figure out if a file is in use?

Hello all,

I'm trying to redirect the standard output stream to file. To complicate things, I might have multiple users running multiple instances of my application, so I want each instance to have its own output file, dynamically assigned when the application starts. I don't want there to be a new file assigned unless necessary, so once a file is no longer in use, I want to recycle it.

So, I'm constructing incrementing file names, then I want to check to see if the file with that name is in use or not by another instance of the application as the output stream. When I hit the first one in the sequence not currently in use, then I'll use that one.

Therein lies my problem, I can't figure out a way to know if a given file is already in use.

Here's the code I'm trying:

////////////////////////////////////////////////

String baseFileName = new String("outfile_");

String currFileName = null;

File theOutFile = null;

for( int i=0; i < MAX_PROG_INSTANCES; i++ )

{

currFileName = baseFileName + i + ".dat";

theOutFile = new File(currFileName);

System.out.println("trying->" + currFileName );

//if this filename hasn't been used before, use it

if ( !theOutFile.exists() )

{

System.out.println("new file name");

break;

}

//try to figure out if the file is in use or not,

// if not, use it.

if( theOutFile.canWrite() )

break;

}//for

System.out.println("using->" + currFileName );

try

{

FileOutputStream fos = new FileOutputStream(theOutFile);

PrintStream ps = new PrintStream(fos);

System.setOut(ps);

System.setErr(ps);

}

catch(java.io.FileNotFoundException ex)

{

System.out.println("ex->" + ex);

}

////////////////////////////////////////////////

File.canWrite() returns true for the file even when it's already in use by another application. I can't make the file readonly or else System.out.println won't be able to write to it. I can't find a method for File or any of the Stream classes that will tell me a given stream/file is already in use.

Any suggestions?

Thanks.

[2268 byte] By [ragnor] at [2007-9-26 1:32:01]
# 1
Try changing the files name when it is in use. and then when the file is done being written to rename it back to the original name
wheaton84 at 2007-6-29 1:32:28 > top of Java-index,Archived Forums,Java Programming...
# 2

I still couldn't figure out a way to make it work by just changing the file name, but your suggestion gave me an idea that does work. Here's my solution in case somebody ever comes up with a similar problem:

The java.io.File class provides two functions that can 'serve as the basis for a simple but reliable cooperative file-locking protocol.' They are:

createNewFile(), which 'Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist. The check for the existence of the file and the creation of the file if it does not exist are a single operation that is atomic with respect to all other filesystem activities that might affect the file.... '

and

deleteOnExit() which 'Requests that the file or directory denoted by this abstract pathname be deleted when the virtual machine terminates....'

So using these two methods I can create a separate lock file using the same naming convention I use to create the output file. If createNewFile() fails, then I know that filename is already in use and to try another one.

Here's the updated code:

/////////////////////////////////

String baseFileName = new String("outfile_");

String baseLockFileName = new String("lockfile_");

String currFileName = null;

String lockFileName = null;

File theOutFile = null;

File lockFile = null;

for( int i=0; i < MAX_PROG_INSTANCES; i++ )

{

currFileName = baseFileName + i + ".dat";

theOutFile = new File(currFileName);

System.out.println("trying->" + currFileName );

//try to figure out if the file is in use or not,

// if not, use it.

lockFileName = baseLockFileName + i + ".dat";

lockFile = new File(lockFileName);

try

{

if ( lockFile.createNewFile() )

{

System.out.println("created lock file!");

lockFile.deleteOnExit();

break;

}

else

{

System.out.println("file in use");

}

}

catch(IOException ioe)

{

System.err.println("Caught IOException->" + ioe);

}

}//for

System.out.println("using->" + currFileName );

try

{

FileOutputStream fos = new FileOutputStream(theOutFile);

PrintStream ps = new PrintStream(fos);

System.setOut(ps);

System.setErr(ps);

}

catch(java.io.FileNotFoundException ex)

{

System.out.println("ex->" + ex);

}

/////////////////////////////////

ragnor at 2007-6-29 1:32:28 > top of Java-index,Archived Forums,Java Programming...
# 3

while a good solution to your problem, the original question is unanswered. As I can't find this answered in this forum, here is the solution I use:

private boolean ckInUse(File oFile) {

if( ! oFile.canRead() ||

! oFile.canWrite() ||

oFile.length() == 0)

return true;

try {

RandomAccessFile randomFile =

new RandomAccessFile(oFile, "rw");

randomFile.close();

}

catch (Exception e) {

return true;

}

return false;

}

hope this helps !

scottrj at 2007-6-29 1:32:28 > top of Java-index,Archived Forums,Java Programming...