Detect File Closure
Hi all,
In my app, users can view and modify files that are stored in the database. This is achieved by getting a byte[] from the DB, writing the file to a temp directory, and then opening with ProcessBuilder or Runtime.exec() ("cmd /c [file path]"). That part's ok.
The issue is that I need to determine when the FILE is closed - not the application that opened the file. This is because if for example Word is started to open a .doc file, the user may make changes to the file and close it, but not close Word, in which case my Java app (if using Process.waitFor()) would still be waiting for the Word process to exit.
I have can monitor the file for changes (lastModified), but this doesn't necessarily mean that the file is closed - just that it's changed.
Upon the file closing I need to automatically rewrite the document to the database, and delete the temp file.
Any thoughts on how to detect closure of the file would be greatly appreciated.
Thanks,
Paul C.
[1018 byte] By [
Pcasanovaa] at [2007-10-3 3:24:42]

For anyone interested, here is the code that finally got it all working:
public void run()
{
try
{
// Write the blob to the selected file
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(sysGenArtifactData.getArtifactData());
fos.flush();
fos.close();
fos = null;
}
catch (FileNotFoundException ex)
{
logger.error(ex);
}
catch (IOException ex)
{
logger.error(ex);
}
ProcessBuilder processBuilder;
Process process;
try
{
// Assemble the startup command
ArrayList<String> list = new ArrayList<String>();
list.add("cmd");
list.add("/c");
list.add("\"" + tempFile.getAbsolutePath() + "\"");
if (logger.isDebugEnabled()) logger.debug(tempFile.getAbsolutePath());
// Initialise the process builder
processBuilder = new ProcessBuilder(list);
processBuilder.directory(tempFile.getParentFile());
// Start the process
process = processBuilder.start();
waitForFileClosure();
if (autoSave)
{
autoSave(tempFile);
}
if (!tempFile.delete())
{
tempFile.deleteOnExit();
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void waitForFileClosure()
{
while(FileUtilities.isFileOpen(tempFile))
{
if (logger.isDebugEnabled()) logger.debug("Waiting for file to be closed: " + tempFile.getAbsolutePath());
ThreadUtilities.waitSeconds(30);
}
if (logger.isDebugEnabled()) logger.debug("File closed: " + tempFile.getAbsolutePath());
}
}
public static boolean isFileOpen(File file)
{
if (logger.isDebugEnabled()) logger.debug("Attempting to aquire file lock on " + file.getAbsolutePath());
boolean isFileOpen = false;
RandomAccessFile raf = null;
FileLock lock = null;
try
{
raf = new RandomAccessFile(file.getAbsolutePath(), "rw");
lock = raf.getChannel().tryLock();
if (lock == null)
{
isFileOpen = true;
}
else
{
lock.release();
}
}
catch (FileNotFoundException ex)
{
isFileOpen = true;
}
catch (IOException ex)
{
isFileOpen = true;
}
finally
{
if (raf != null)
{
try
{
raf.close();
raf = null;
}
catch (IOException ex)
{
logger.error(ex);
}
}
}
if (logger.isDebugEnabled()) logger.debug("File open status for " + file.getAbsolutePath() + ": " + isFileOpen);
return isFileOpen;
}
Thanks to everyone for their help,
Paul C.