What is wrong with FileInputStream.read (byte [])?

In response to my answer to a question about reading a file, the commentator stated that FileInputStream.read(byte[]) "does not guarantee buffer filling."

 File file = /* ... */ long len = file.length(); byte[] buffer = new byte[(int)len]; FileInputStream in = new FileInputStream(file); in.read(buffer); 

(the code assumes that the file length does not exceed 2 GB)

Besides an IOException , what can cause the read method to not retrieve the entire contents of a file?

EDIT:

The idea of ​​the code (and the purpose of the OP question I answered) is to read the entire file into a piece of memory in one fell swoop, therefore buffer_size = file_size .

+7
source share
6 answers

Besides the IOException, what can cause the read method not to retrieve the entire contents of the file?

In my own implementation of the API, and in my home loaded file system, I just want to fill half the buffer ... just kidding.

I can say that even if I were not joking, technically speaking, this would not be a mistake. This is a matter of contract method. This is a contract (documentation) in this case:

Reads up to b.length bytes of data from this input stream into an array of bytes.

ie, it does not give guarantees for filling the buffer.

Depending on the implementation of the API, and possibly on the file system, the read method may not fill the buffer. This is basically a question of what the method contract says.


Bottom line: This probably works, but it is not guaranteed to work.

+5
source

what might cause the read method not to extract the entire contents of the file?

If, for example, the file is fragmented in the file system and the low-level implementation knows that it will have to wait until HD starts looking for the next fragment (this is something that takes a lot of time relative to the operation processor), it would be wise for the read() call returned with a part of an empty buffer to give the application a chance to already do something with the data it received.

Now I do not know if any implementation actually works, but the fact is that you should not rely on a filled buffer, because this is not guaranteed by the API contract.

+6
source

Well, first you made a false dichotomy. One completely normal circumstance is that the buffer will not be full because there are not many bytes left in the file. This is not an IOException , but this does not mean that the contents of the entire file has not been read.

The spectrum says that the method will either return -1, indicating the end of the stream, or block until at least one byte is read. Artists of InputStream can optimize as they match (for example, a TCP stream can return data as soon as a packet arrives, regardless of the choice of buffer size). A FileInputStream can fill a buffer with a single data block. As the caller, you have no idea, except when the method returns -1 , you need to continue reading.

Edit

In practice, in your example, the only circumstance that I will see where the buffer will not be filled (with the standard implementation) is if the file size has changed after you allocated the buffer, but before you start reading it. Since you did not lock the file, this is possible.

+3
source

People talked about reading on a FileInputStream , because they hypothetically did not fill the buffer. In fact, in some cases this is reality:

  • If you open FileInputStream on "/ dev / tty" or the named pipe, then read will only return the data that is currently available to you. Other device files may behave the same. (These files will probably return 0L as the file size.)

  • A FUSE file system can be implemented to not completely fill the read buffer if the file system was mounted using direct_io , or the file is opened with the appropriate flag.

The above requirements apply to Linux, but there may well be similar cases for other operating systems and / or Java implementations. The bottom line is that javadocs allows this behavior, and you may run into problems if your application assumes that this will not happen.

There are third-party libraries that implement the "read fully" behavior; for example, Apache commons provides FileUtils.readFileToByteArray or IOUtils.toByteArray and similar methods. If you want / need this behavior, you must use one of these libraries or implement it yourself.

+2
source

Not guaranteed Fill buffer.

The file size may be smaller than the buffer, or the remainder of the file may be smaller than the buffer.

+1
source

Your question is controversial. There is no guarantee that he will read the entire buffer, even if there are no conceivable circumstances in which this will not happen. There is no guarantee, therefore you cannot allow this.

0
source

All Articles