How to know if a RandomAccessFile is closed

P

Philipp

Hello
I need to write data to a RandomAccessFile. The data arrive in a
random way throughout time.
I'm searching for the optimal way of ensuring that the file is closed
in case the app shuts down and that the data has been flushed no too
long ago if the app crashes.
For now, I'm opening the file at each pack of data which arrives
(typically only one byte), write it to the file and close the file.
Is this very inefficient?
Should I keep the file open for long times (and maybe close it in a
(dreaded) finalizer)? If it all possible, I would like to not put the
burden on the user of my class to call some shutdown() method.
Is there a way to test whether a file has been closed before?

Thanks for answers (although I posting through GG :)
Phil
 
T

Tom Anderson

random way throughout time.
I'm searching for the optimal way of ensuring that the file is closed
in case the app shuts down and that the data has been flushed no too
long ago if the app crashes.
For now, I'm opening the file at each pack of data which arrives
(typically only one byte), write it to the file and close the file.
Is this very inefficient?
Should I keep the file open for long times (and maybe close it in a
(dreaded) finalizer)? If it all possible, I would like to not put the
burden on the user of my class to call some shutdown() method.
Is there a way to test whether a file has been closed before?

Your problem is not actually making sure the file gets closed, but that
the changes you have made to it get written to disk. Closing it does that,
but there is another way:

RandomAccessFile f ;
f.getFD().sync() ;

That flushes the file, and leaves it open.

I would say you should open the file when the object is created, write
data when it arrives, and sync() it every so often. You should provide a
close() or shutdown() method, and encourage the client to call it, but if
you sync, it shouldn't be necessary to maintain data integrity. A
finalizer, or some PhantomReference-based solution, might be a nice thing
to add, to prevent the app leaking file handles.

There is a question as to when you should sync. You could do it after
every packet, for maximum reliability. You could do it periodically, every
10 seconds or something (skipping a sync if there haven't been any
changes). You could sync after a period of inactivity (say if there
haven't been any writes for 10 seconds).

One caveat: it's not entirely clear that sync() is 100% guaranteed to
flush everything to disk on all platforms. In practice, though, i think
it's fine.

tom
 
P

Philipp

Your problem is not actually making sure the file gets closed, but that
the changes you have made to it get written to disk. Closing it does that,
but there is another way:

RandomAccessFile f ;
f.getFD().sync() ;

That flushes the file, and leaves it open.

I would say you should open the file when the object is created, write
data when it arrives, and sync() it every so often. You should provide a
close() or shutdown() method, and encourage the client to call it, but if
you sync, it shouldn't be necessary to maintain data integrity. A
finalizer, or some PhantomReference-based solution, might be a nice thing
to add, to prevent the app leaking file handles.

There is a question as to when you should sync. You could do it after
every packet, for maximum reliability. You could do it periodically, every
10 seconds or something (skipping a sync if there haven't been any
changes). You could sync after a period of inactivity (say if there
haven't been any writes for 10 seconds).

One caveat: it's not entirely clear that sync() is 100% guaranteed to
flush everything to disk on all platforms. In practice, though, i think
it's fine.

Thanks for that answer. I didn't know the sync() method, so I will
follow your advice.
I have one more question. Is there a way to know if a RandomAccessFile
has been closed?
If the user of my class calls close() and later some more data arrive
I would like to reopen the file and write the data. I imagine a test
like:

if(randomAccessFile.isClosed()){
//reopen it
}
writeData();

Thanks Phil
 
T

Tom Anderson

Thanks for that answer. I didn't know the sync() method, so I will
follow your advice.
I have one more question. Is there a way to know if a RandomAccessFile
has been closed?

Not that i know of.

Well, you could do this:

public boolean isOpen(RandomAccessFile f) {
try {
f.length() ;
return true ;
}
catch (IOException e) {
return false ;
}
}
If the user of my class calls close() and later some more data arrive
I would like to reopen the file and write the data. I imagine a test
like:

if(randomAccessFile.isClosed()){
//reopen it
}
writeData();

Instead of looking at whether the file is closed, keep track of the state
in your class. Like so:

import java.io.* ;

public class PhilippsClass {
private File f ;
private RandomAccessFile raf ;
private boolean isOpen ;
private long filePointer ;

public PhilippsClass(File f) {
this.f = f ;
}
public void write(byte[] buf) throws IOException {
open() ;
raf.write(buf) ;
raf.getFD().sync() ;
filePointer = raf.getFilePointer() ;
}
public void open() throws IOException {
if (!isOpen) {
raf = new RandomAccessFile(f, "rw") ;
raf.seek(filePointer) ;
isOpen = true ;
}
}
public void close() throws IOException {
if (isOpen) {
try {
raf.close() ;
}
finally {
isOpen = false ;
}
}
}

public static void main(String[] args) throws IOException {
PhilippsClass pc = new PhilippsClass(new File(args[0])) ;
pc.write("hello world!\n".getBytes("UTF-8")) ;
pc.write("hello again!\n".getBytes("UTF-8")) ;
pc.close() ;
pc.write("hello once more!\n".getBytes("UTF-8")) ;
}

}

You'll note that i also keep track of the offset at which you're writing
in the file, which RandomAccessFile calls the file pointer, since that
gets reset when you reopen the RandomAccessFile. An alternative would be
to do that only in close(), so the file pointer is only stored when the
file isn't open.

As an alternative to storing a flag, you could null the variable holding
the RandomAccessFile, and examine that:

import java.io.* ;

public class PhilippsClass {
private File f ;
private RandomAccessFile raf ;
private long filePointer ;

public PhilippsClass(File f) {
this.f = f ;
}
public void write(byte[] buf) throws IOException {
open() ;
raf.write(buf) ;
raf.getFD().sync() ;
filePointer = raf.getFilePointer() ;
}
public void open() throws IOException {
if (!isOpen()) {
raf = new RandomAccessFile(f, "rw") ;
try {
raf.seek(filePointer) ;
}
catch (IOException e) {
raf = null ; // something went wrong, throw away the file
}
}
}
public void close() throws IOException {
if (isOpen()) {
try {
raf.close() ;
}
finally {
raf = null ;
}
}
}
public boolean isOpen() {
return raf != null ;
}

public static void main(String[] args) throws IOException {
PhilippsClass pc = new PhilippsClass(new File(args[0])) ;
pc.write("hello world!\n".getBytes("UTF-8")) ;
pc.write("hello again!\n".getBytes("UTF-8")) ;
pc.close() ;
pc.write("hello once more!\n".getBytes("UTF-8")) ;
}
}

tom
 
S

Stanimir Stamenkov

Wed, 16 Jul 2008 06:10:44 -0700 (PDT), /Philipp/:
I have one more question. Is there a way to know if a RandomAccessFile
has been closed?

The FileDescriptor.valid() method should give you just that
information
*Returns*:
true if the file descriptor object represents a valid,
_open file_, socket, or other active I/O connection; false otherwise.

RandomAccessFile f;
...
if (f.getFD().valid()) {
...
}

With Java 1.4 and later I see one could test, also:

RandomAccessFile f;
...
if (f.getChannel().isOpen()) {
...
}

To ensure data has been immediately written to disk you could
construct the RandomAccessFile with "rws" or "rwd" mode [1], as
alternative to explicitly calling FileDescriptor.sync().

[1]
http://java.sun.com/j2se/1.5.0/docs...ccessFile(java.lang.String, java.lang.String)
 
A

Arne Vajhøj

Philipp said:
I need to write data to a RandomAccessFile. The data arrive in a
random way throughout time.
I'm searching for the optimal way of ensuring that the file is closed
in case the app shuts down and that the data has been flushed no too
long ago if the app crashes.
For now, I'm opening the file at each pack of data which arrives
(typically only one byte), write it to the file and close the file.
Is this very inefficient?
Should I keep the file open for long times (and maybe close it in a
(dreaded) finalizer)? If it all possible, I would like to not put the
burden on the user of my class to call some shutdown() method.
Is there a way to test whether a file has been closed before?

Keep it open. And have a close method. Opening a file is
a relative costly operation. And it is a common
paradigm that it is the responsibility of the one that
open to do the close. The finally keyword exist to help doing that.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top