Java file transfer client does not read all bytes

I have a sender and a recipient of files. Out of 10 or so posts I found on the internet, this is the correct way to send files over sockets in Java. Take a look at the code snippets below.

Sender:

OutputStream bos = clientSocket.getOutputStream();
FileInputStream fis = new FileInputStream(sendingFile);
BufferedInputStream bis = new BufferedInputStream(fis);

int n;
int total = 0;
byte[] buffer = new byte[8192];

while ((n = bis.read(buffer)) > 0) {
    bos.write(buffer, 0, n);
    System.out.println("Sending File... ");
    total += n;
    System.out.println(total);
}

      

Recipient:

InputStream bis = clientSocket.getInputStream();
FileOutputStream fos = new FileOutputStream(fileOut);
BufferedOutputStream bos = new BufferedOutputStream(fos);

int n;
int total = 0;
byte[] buffer = new byte[8192];
while ((n = bis.read(buffer)) > -1) {
    bos.write(buffer, 0, buffer.length);
    System.out.println("Writing File... ");
    total += n;
    System.out.println(total);
    if (total == fileSize) {
        break;
    }
}
System.out.println("File Received");

      

Here's the output from the sender

File upload: D: \ Users \ Administrator \ Documents \ AAAAAAAAAAAAAAAAAAAAAAAAA.avi
File size: 54236160
File upload ...
8192
File upload ...
16384
................... . after a while
Sending file ...
54231040
send a file ...
54236160
file sent

The last number, 54236160, is the exact size of the file being uploaded. Now here is the last line on the receiver side.

Writing the file ...
54234710

So, for that particular file, it always stops at that size, and so since the entire file is not being sent, the receiver never stops waiting for data. I don't understand how the sender is sending the correct amount of data, but the receiver is not receiving everything. I never see "Received File" on the receiver side and the amount of data the receiver reads is never equal to the amount being sent.

This problem occurs for any file I send, and if I send really small files like those in bytes and not kb, I don't see any "Writing a file ..." on the recipient side at all, almost just ignore flow.

However, all the posts on the internet say this is the correct way to send files. Oh, and if I close the sending socket and / or stream, which I don't want to do because there are other things the client and server have to do, it still doesn't fix the problem.

Another thing I noticed is that while the sender always seems to point to its full buffer write (always a multiple of 8192 for "total"), the receiver does not.

Below is the code that gets the files and the filename. Could this be a bug? I don't see how all of this is done before we start sending and receiving the file.

System.out.println("Receiving File");
try {
    clientScanner.nextLine();
    String fileName = clientScanner.nextLine();
    int fileSize = clientScanner.nextInt();
    System.out.println("File: " + fileName + " Size: " + fileSize);
    File fileOut = new File("C:\\Users\\owner\\AppData\\Local\\temp\\" + fileName);

    InputStream bis = clientSocket.getInputStream();
    FileOutputStream fos = new FileOutputStream(fileOut);
    BufferedOutputStream bos = new BufferedOutputStream(fos);

      

+3


source to share


1 answer


You shouldn't try to read more data than expected. Your loop should be:

int n;
int bytesLeft = fileSize;
byte[] buffer = new byte[8192];
while (bytesLeft > 0) {
    int n = bis.read(buffer, 0, Math.min(buffer.length, bytesLeft));
    if (n < 0) {
        throw new EOFException("Expected " + bytesLeft + " more bytes to read");
    }
    bos.write(buffer, 0, n);
    System.out.println("Writing File... ");
    bytesLeft -= n;
    System.out.println(total " bytes left to read");
}

      

(You can customize the output to show how many bytes you've read, rather than how many you have left to read if you like, but I think this approach is simpler.)

If that still doesn't give you all the data, then you should flush the output stream in your email code - I wouldn't expect you to, but if you don't close the socket, I think that might buffer it forever.

If the loop finishes but the file seems incomplete, make sure you close bos

after all this.



If none of this helps, it is possible that something else read the beginning of your data before you enter this loop. You have to compare the data in the output file with the original file. Look at the first (say) 16 bytes in the output file and make sure they are at the beginning of the input file. If it is not, then it suggests that the problem is related to what you are doing with the connection before the code you showed us. (For example, the code used to send and receive the expected file size.)

Now that we can see how you send / receive file size, this is definitely a problem. The scanner is reading some of the file data. To fix this, just use DataOutputStream

on the send side and DataInputStream

on the receiving side:

DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream());
output.writeUTF(fileName);
output.writeInt(fileSize);
// Write the data as before, to output

      

On the receiving side:

DataInputStream input = new DataOutputStream(clientSocket.getInputStream());
String fileName = input.readUTF(name);
int fileSize = input.readInt();
// Read the data before, as above, from input

      

+4


source







All Articles