Reputation: 9351
I am trying to do something like in this first example of code below that is non-blocking but it gives corrupted files. The second example works fine but it is blocking, if you don't close the socket of output stream from the client side (other side), which is the other device this sever is connected to, then it will block and thread execution will not go any farther than that.
What is wrong with the first piece of code that causes it to produce corrupted files every time?
First example code, good idea but produces corrupted files;
while(totalBytesRead < fileSizeFromClient){
int bytesRemaining = fileSizeFromClient - totalBytesRead;
int bytesRead = bufferedInputStream.read(buffer, totalBytesRead, bytesRemaining);
bufferedOutputStream.write(buffer, totalBytesRead, bytesRemaining);
if(bytesRead == -1){
break;
}else{
totalBytesRead += bytesRead;
}
}
Second example, code gets stuck; blocks. So I can't use this, as you have to kill the socket from the client side to get code execution to continue beyond these lines of code. But it produces perfect uncorrupted files.
while((count = bufferedInputStream.read(buffer)) > 0){
bufferedOutputStream.write(buffer, 0, count);
}
Upvotes: 0
Views: 119
Reputation: 111219
This line writes all of the "remaining" bytes, even if only one byte was read, and also potentially writes something if read
returned -1 signaling the end of input:
bufferedOutputStream.write(buffer, totalBytesRead, bytesRemaining);
To write only the bytes that were read, pass the number of bytes that were read as the third parameter.
int bytesRead = bufferedInputStream.read(buffer, totalBytesRead, bytesRemaining);
if (bytesRead == -1) {
break;
} else {
bufferedOutputStream.write(buffer, totalBytesRead, bytesRead);
totalBytesRead += bytesRead;
}
There is no reason why the second code should block and this one not, though.
Also note that this way you are creating an in-memory copy of the data that you are transferring, which may occupy a lot of memory or make the program fail with ArrayIndexOutOfBoundsException
if the buffer is not big enough. If that was not your intention you should use 0
instead of totalBytesRead
as the array offset when reading and writing, and limit the number of bytes read to the size of the buffer. After these transformations the code would look like this:
int bytesRead = bufferedInputStream.read(buffer);
if (bytesRead == -1) {
break;
} else {
bufferedOutputStream.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
}
As you can see, it is almost identical to your second example, which you say "blocks."
Upvotes: 0
Reputation: 310860
bytesRead == -1
should precede the write, not follow it.write()
should be bytesRead
.read()
and write()
should be zero.Upvotes: 1