Forum Stats

  • 3,815,470 Users
  • 2,259,032 Discussions
  • 7,893,112 Comments

Discussions

java.io.FileInputStream read() method

OrhanCemalDuru
OrhanCemalDuru Member Posts: 6
edited Jul 31, 2018 11:53AM in Java Programming

Just to vendor a thought, I wonder why the read methods of FileInputStream do not return a boolean value. Let me describe:

The description of  read(byte[], offset, length) states that it returns an integer, switching two cases:

"the total number of bytes read into buffer, or -1 if there is no more data because the eof is reached."

What if the array length is not reached after eof? The first thing that comes to my mind is that it should throw an exception, because the allocated memory of byte array is not fulfilled.

Say it returns -1 for not throwing an exception, then the byte array is full. What's the point of returning that value (the total number of bytes) which is array.length?

OrhanCemalDuru

Best Answer

  • Unknown
    edited Apr 5, 2018 3:30PM Answer ✓
    In your reply to #3 you say  first the method you refer to is used when you do NOT want to fill the buffer. That is why you can specify the number of characters you want as well as the offset to put them.reminding the method read(byte[], offset, length)

    What I should have said was you don't NECESSARILY want to fill the buffer.

    NONE of the methods guarantee that the buffer will be filled. The number of bytes is limited by what is available to read.

    My first question is that when we do not fill the buffer using an offset, how does it fill the unassigned bytes of the buffer. 

    It doesn't do that for ANY of the methods. The methods just read bytes that are available. You can put a MAX limit but there is no guarantee that 'length' bytes will be read - that is the MAXIMUM NUMBER that will be read.

    There ARE NO UNASSIGNED bytes in a buffer of a primitive type that has a non-zero length. You can test that yourself. Declare a buffer of a given length and examine it in NetBeans. Every element will have the same value and that value will be the default for that datatype which is zero.

    It's sort of distracting.

    I have NO IDEA what that even means.

     There's no option that it leaves them unassigned.

    ALL ELEMENTS of primitive arrays have a value. You can change that value. And if you use the read (array, off, length) method you can replace a sequential series of bytes with a new value.

    But 'unassigned' has NO MEANING at all in Java for primitive arrays.

    Then there must be a fixed value for filling the rest of the bytes (the prefix).

    Again - try to understand the concept.

    There is NOTHING TO FILL. There ARE NO UNASSIGNED bytes in a buffer of a primitive type that has a non-zero length.

    The length of a file could be guessed by FileInputStream.available(),

    No - focus on the word 'stream'. That class works on STREAMS - not files. Refer to the API for that method

    https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html

    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.<strong><a href="https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#available()">available</a></strong>()

    At best that is an 'estimate'. For streams how can you possibly know how much more data might be out there? I can write a socket program that just keeps feeding data to the socket forever and never ends. The receiving socket can't possibly know how much more data the sender might send.

    and could be determined by File.length().

    That applies to FILES - not streams.

     Obviously, I want to read the whole file and store it.

    How is it 'obvious' to Java code what you want to read or do?

    For that reason I chose to create the buffer using FileInputStream.read(byte[]) - the single parameter, and declare the array using File.length(). But this method is returning long type. How can I declare the buffer using long?

    Why would you want to store an entire file (that could be Gigabytes in length) in memory? That generally doesn't make any sense.

    Anyway none of the above quote has ANYTHING to do with the topic of this thread which is about the read method.

    Arrays are declared using integers so the max size of an array is the max size of an integer. You can't declare an array longer than the max size of an integer.


    OrhanCemalDuru

Answers

  • Unknown
    edited Apr 1, 2018 6:01PM
    Just to vendor a thought, I wonder why the read methods of FileInputStream do not return a boolean value.

    The 'logical' answer is they return 'int' because the NUMBER OF BYTES read is the most important/valuable piece of information there is. If the method returned 'boolean' then how would you know how many bytes had been read?

    Have you read the API for that method?

    https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#read(byte[],%20int,%20int)

    Returns:the total number of bytes read into the buffer, or -1 if there is no more data because the end of the file has been reached.

    So if the buffer is 10 bytes long and you want to read 5 bytes and put them at offset 2 but there are only 2 bytes left to read how would you know that Java only read 2 bytes instead of the '5 max' you ask for if boolean was returned?

    Here's a thought.

    Make a list of ALL POSSIBLE outcomes from a read method.

    Now explain how returning BOOLEAN can cover all of those outcomes.

    How long should we wait for your reply?

    The description of read(byte[], offset, length) states that it returns an integer, switching two cases:

    Correct - ALL of the 'read' methods return int because the class extends the abstract class InputStream and that class declares the three 'read' methods that will then be part of ALL extending classes.

    So your question really becomes why does the abstract class InputStream use an 'int' return type. For the reason stated above.

    Done with that list above yet? That should tell you there are more than two outcomes for the method call.

    The description of read(byte[], offset, length) states that it returns an integer, switching two cases:"the total number of bytes read into buffer, or -1 if there is no more data because the eof is reached."What if the array length is not reached after eof? The first thing that comes to my mind is that it should throw an exception, because the allocated memory of byte array is not fulfilled.Say it returns -1 for not throwing an exception, then the byte array is full. What's the point of returning that value (the total number of bytes) which is array.length?

    #1 above - correct

    #2 above - not sure where you got that quote this is what the Java 7 API doc says

    Returns:
    the total number of bytes read into the buffer, or -1 if there is no more data because the end of the file has been reached.

    Your quote says 'eof is reached'. The quote above says 'has been reached' - has been can include the case where the previous read read the last byte but did NOT trigger an EOF indication.

    #3 above - array length is not reached after eof - first the method you refer to is used when you do NOT want to fill the buffer. That is why you can specify the number of characters you want as well as the offset to put them.

    If the method was just used to FILL the buffer there would be no need for the 'len' parameter since Java already knows how long the buffer is and the 'off' parameter then would let it know how many to read to fill the buffer.

    #4 above is WRONG -

    Say it returns -1 for not throwing an exception, then the byte array is full.

    NO! A return of -1 says there is no more data. It does NOT mean the 'array is full'. As just explained for #3 maybe NO BYTES at all were read because the previous read exhausted them all. Then when you try to read some there aren't any so -1 is returned. That has NOTHING TO DO with how full the buffer is.

    You don't want an exception to be thrown just because Java can't read all of the bytes you ask for. REREAD the description for the 'len' parameter:

     - the maximum number of bytes read.len

    See that word 'maximum'? You do NOT ask for a specific number of bytes. You ask for a MAXIMUM number of bytes. That means that Java won't read MORE THAN what you ask for. But it could read less, even zero.

  • OrhanCemalDuru
    OrhanCemalDuru Member Posts: 6
    edited Apr 5, 2018 2:29PM

    Thank youfor your reply.

    I agree with most of it and I reconsidered my knowledge. I want take the discussion a step further.

    In your reply to #3 you say

     first the method you refer to is used when you do NOT want to fill the buffer. That is why you can specify the number of characters you want as well as the offset to put them.

    reminding the method read(byte[], offset, length)

    My first question is that when we do not fill the buffer using an offset, how does it fill the unassigned bytes of the buffer. It's sort of distracting. There's no option that it leaves them unassigned. Then there must be a fixed value for filling the rest of the bytes (the prefix). It's distracting. Anyway, I discard it.

    The second question is more practical. The length of a file could be guessed by FileInputStream.available(), and could be determined by File.length(). Obviously, I want to read the whole file and store it. For that reason I chose to create the buffer using FileInputStream.read(byte[]) - the single parameter, and declare the array using File.length(). But this method is returning long type. How can I declare the buffer using long?

  • Unknown
    edited Apr 5, 2018 3:30PM Answer ✓
    In your reply to #3 you say  first the method you refer to is used when you do NOT want to fill the buffer. That is why you can specify the number of characters you want as well as the offset to put them.reminding the method read(byte[], offset, length)

    What I should have said was you don't NECESSARILY want to fill the buffer.

    NONE of the methods guarantee that the buffer will be filled. The number of bytes is limited by what is available to read.

    My first question is that when we do not fill the buffer using an offset, how does it fill the unassigned bytes of the buffer. 

    It doesn't do that for ANY of the methods. The methods just read bytes that are available. You can put a MAX limit but there is no guarantee that 'length' bytes will be read - that is the MAXIMUM NUMBER that will be read.

    There ARE NO UNASSIGNED bytes in a buffer of a primitive type that has a non-zero length. You can test that yourself. Declare a buffer of a given length and examine it in NetBeans. Every element will have the same value and that value will be the default for that datatype which is zero.

    It's sort of distracting.

    I have NO IDEA what that even means.

     There's no option that it leaves them unassigned.

    ALL ELEMENTS of primitive arrays have a value. You can change that value. And if you use the read (array, off, length) method you can replace a sequential series of bytes with a new value.

    But 'unassigned' has NO MEANING at all in Java for primitive arrays.

    Then there must be a fixed value for filling the rest of the bytes (the prefix).

    Again - try to understand the concept.

    There is NOTHING TO FILL. There ARE NO UNASSIGNED bytes in a buffer of a primitive type that has a non-zero length.

    The length of a file could be guessed by FileInputStream.available(),

    No - focus on the word 'stream'. That class works on STREAMS - not files. Refer to the API for that method

    https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html

    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.<strong><a href="https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#available()">available</a></strong>()

    At best that is an 'estimate'. For streams how can you possibly know how much more data might be out there? I can write a socket program that just keeps feeding data to the socket forever and never ends. The receiving socket can't possibly know how much more data the sender might send.

    and could be determined by File.length().

    That applies to FILES - not streams.

     Obviously, I want to read the whole file and store it.

    How is it 'obvious' to Java code what you want to read or do?

    For that reason I chose to create the buffer using FileInputStream.read(byte[]) - the single parameter, and declare the array using File.length(). But this method is returning long type. How can I declare the buffer using long?

    Why would you want to store an entire file (that could be Gigabytes in length) in memory? That generally doesn't make any sense.

    Anyway none of the above quote has ANYTHING to do with the topic of this thread which is about the read method.

    Arrays are declared using integers so the max size of an array is the max size of an integer. You can't declare an array longer than the max size of an integer.


    OrhanCemalDuru
  • EJP
    EJP Member Posts: 32,920 Gold Crown
    edited Apr 12, 2018 8:24PM

    > I wonder why the read methods of FileInputStream do not return a boolean value.

    Because they override the read() methods defined by InputStream, whose contracts are already defined therein, and because what they do - returning an int - is more useful: which is why they are defined that way.

    > What if the array length is not reached after eof?

    It returns "the total number of bytes read into buffer."

    > The first thing that comes to my mind is that it should throw an exception, because the allocated memory of byte array is not fulfilled.

    Why? Where does it say the buffer should be filled?

    > Say it returns -1 for not throwing an exception, then the byte array is full.

    'Returns -1 for not throwing an exception' doesn't make any sense, and it doesn't return -1 if the array is full. It returns -1 at end of stream, or a byte count if any data was read.

    > What's the point of returning that value (the total number of bytes) which is array.length?

    No it isn't. Read the Javadoc. 'Reads up to b.length bytes of data from this input stream into an array of bytes'. If fewer bytes were read, you need to know how many. This is certain to happen at the end of the file, unless the file size is magically a multiple of the array size and all prior reads filled the array, which isn't guaranteed.

  • Unknown
    edited Apr 13, 2018 12:03AM
This discussion has been closed.