Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

May the FileInputStream.available foolish me?

Tags:

java

file-io

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.

like image 510
The Student Avatar asked May 07 '10 13:05

The Student


1 Answers

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.

like image 169
Stephen C Avatar answered Sep 22 '22 09:09

Stephen C