tags:

views:

129

answers:

4

This FileInputStream.available() javadoc says:

Returns an estimate of the number of remaining bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream. The next invocation might be the same thread or another thread. A single read or skip of this many bytes will not block, but may read or skip fewer bytes.

In some cases, a non-blocking read (or skip) may appear to be blocked when it is merely slow, for example when reading large files over slow networks.

I'm not sure if in this check:

if (new FileInputStream(xmlFile).available() == 0)

can I rely that empty files will always return zero?

--

Thanks @SB, who does not exactly answered the question, but was the first to give the best alternative:

If xmlFile is a java.io.File object, you can use the length() method to get its size.

+2  A: 

I strongly advise against using available() - it can return 0 because the stream is blocked, even though there are still enough bytes to read. It probably won't occur with Files but the API does not guarantee it won't.

The same approach can be used with read() though:

if (new FileInputStream(xmlFile).read() == -1)  
  System.out.println("!!File empty!!");  
Cristian
+2  A: 

If xmlFile is a java.io.File object, you can use the length() method to get its size.

SB
@SB - however, `File.length()` returns zero in situations other than a zero length file; see the javadoc.
Stephen C
Stephen - good point, but I think it's a better alternative than using available. What does available do if the file is a directory or does not exist? My guess is it returns 0, but it can also return 0 if the size is > 0.
SB
+2  A: 

My logical answer to the question "can I rely that empty files will always return zero?" is "Yes, for empty files, available() will return 0".

But you probably do also want to know "can I rely that only empty files will return zero?", and there the answer is "No, not by specification: available() might return 0 even if the file is not empty".

Additionally, you are opening a stream on a file and do not close it again. This may lead to unexpected and undesired behaviour, e.g. you may not be able to move or delete the file as long as your Java program is running. This is especially annoying if your program runs in an application server which usually runs for a very long time, making the file effectively immutable.

Christian Semrau
+1  A: 

You can rely on new FileInputStream(fileName).available() returning zero if the named file is empty.

You cannot rely on new FileInputStream(fileName).available() == 0 as a definitive test that the file is empty. If fileName is a regular file on a local file system it will probably work. But if fileName is a device file or if it is a file on a remote file system, available() may return zero to report that a read() will have to block for a period. (Or in the case of a remote file system, it may not.)

A more reliable way to test the length of a regular file is to use new File(fileName).length() == 0. However for a device file or pipe, a length() call may return zero, irrespective of the number of bytes that can ultimately be read. And bear in mind that new File(fileName).length() also returns zero if the file does not exist.

EDIT If you want a reliable test to see if a file is empty, you have to make a number of calls:

public static isEmptyFile(String fileName) {
    File file = new File(fileName);
    if (!file.exists()) {
        return false;
    } else if (file.length() != 0L) {
        return false;
    } else if (file.isFile()) {
        return true;
    } else if (file.isDirectory()) {
        return false;
    } else {
        // It may be impossible to tell that a device file / named pipe is
        // "empty" without actually reading it.  This is not a failing of
        // Java: it is a logical consequence of the way that certain
        // devices, etc work.
        throw new CannotAnswerException(...);
    }
}        

But you would be well advised to test this carefully with a variety of "file" types on all platforms that you run your application on. The behavior of some of the file predicates is documented as being platform specific; see the javadoc.

Stephen C
So I either can't rely on length()? There is no reliable test?
Tom Brito