Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

DataInputStream  RSS feed

 
Andrew Lit
Ranch Hand
Posts: 135
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can't understand why this doesn't download all file from the web, the number of bytes less than 1024 are not downloaded:

Documentation:
Returns:
the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.
Maybe i missed something. Thank you for the help.
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The problem may lie in the fact that you are reading exactly 1024 bytes from the InputStream each time... This means that exactly 1024 bytes (the entire length of the array) will be outputted at once, even if the length of the file is not divisible by 1024, but instead gives a remainder.
I've tested your code, and it produces files which (surprise, surprise) are a multiple of 1024 bytes long... Of course, these extra bytes written will cause file corruptions. I tried downloading a PDF document, which subsequently failed to open with a "could not repair file" error!
If you are copying files, this is not so much of a problem, because you can determine the length of the source file, and adjust the buffer length to be a factor of the total length as necesssary. However, over the Internet, there is no guaranteed method for finding the length, although the best way is to get the "Content-Length" parameter of the response's header. This can be found in the URLConnection class, an object of which can be obtained from a URL.openConnection() call.
I think it would be best if you now proceeded in one of two ways:
  • Read and write only one byte at a time until the InputStream indicates an EndOfFile. In this case, avoid using a buffer at all.
  • Or, write a test so that a counter is incremented on every iteration of your read/write loop, keeping track of the currently read size; then on the last read (which may not be divisible by 1024 bytes) you need to write only the remaining bytes [calculated by subtracting the currently read bytes from the total length] to the file (otherwise you run the risk of writing some of the data, which is left at the end in the unchanged bytes, from a previous read).


  • I hope this helps, because I couldn't find a better explanation!
    [ June 10, 2003: Message edited by: Charles Lyons ]
     
    Andrew Lit
    Ranch Hand
    Posts: 135
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thank you for the reply i also thought of that, but i can't determine the end of the file correctly. I tried to change my loop this way:

    but i get the same result - file is being downloaded incorrectly. Also tried getContentLength(); as you suggested but this function didn't help too much, because in most cases it returned -1. So what is the solution? How to download a file from the web?
    thank you.
     
    Charles Lyons
    Author
    Ranch Hand
    Posts: 836
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Your code here will still write one extra byte to the end, because it is only until the end of the while loop that the byte "bb" will be assigned -1 at the end of the file. You need to test if the next byte is -1 before entering the loop, not write an extra -1 before leaving the loop (if you see what I mean).
    If the "Content-Length" is returning -1, then the server is not returning the required parameter in an HTTP/1.1 response header. This is common in some server models.
    Try the following, which (as I said above) checks the status of the end of file (the -1 returned) before writing it out):

    Despite being an integer primitive in the code, believe it or not, only a byte is written. See the contracts between the single-byte read/write input/output stream methods in the documentation for further information.
     
    Consider Paul's rocket mass heater.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!