Reputation: 35
I've been working on a chat client for myself and some friends, and decided to attempt to add functionality to allow file transfers between clients. I am able to send a file, but it arrives in a different state than the file sent. As an example, here is a link comparing the before and after of an image sent:
https://i.sstatic.net/VJkOE.jpg
Don't ask why I used that picture, it's just the first one I found in my pictures folder... And here are the send and receive methods:
public static Runnable sendFile(String target, File file, Client client) {
Runnable run = () -> {
FileOutputStream fileOut = null;
try {
int total = 0;
int count;
byte[] fileBuffer = new byte[8192];
BufferedInputStream fileStream = new BufferedInputStream(new FileInputStream(file));
client.getTextOutData().writeUTF("*!sendfile: " + client.getClientName() + " " + target + " " + file.getName() + " " + (int) file.length());
fileOut = new FileOutputStream(new File(downloadsPath + "/" + file.getName()));
System.out.println("Send length: " + file.length());
while ((count = fileStream.read(fileBuffer, 0, (int) Math.min(8192, file.length() - total))) == 8192) {
total += count;
System.out.println("Sender count: " + count);
client.getDLOutData().write(fileBuffer, 0, count);
client.getDLOutData().flush();
fileOut.write(fileBuffer, 0, count);
}
total += count;
System.out.println("Sender count: " + count);
System.out.println("Sender total: " + total);
//client.getDLOutData().write(fileBuffer, 0, count);
fileOut.write(fileBuffer, 0, count);
System.out.println("Sending done, eh?");
fileStream.close();
Thread.currentThread().interrupt();
} catch (Exception e) {
Platform.runLater(() ->Popups.startInfoDlg("Download Error", "Failed to send file!"));
e.printStackTrace();
}
};
return run;
}
public static Runnable dlFile(MainScreenController sc, File file, long length) {
Runnable run = () -> {
FileOutputStream fileOut = null;
try {
int total = 0;
int count;
byte[] fileBuffer = new byte[8192];
fileOut = new FileOutputStream(file);
System.out.println("DL length: " + length);
while ((count = sc.getClient().getDLInData().read(fileBuffer, 0, (int) Math.min(8192, length - total))) == 8192){
total += count;
System.out.println("DL count: " + count);
fileOut.write(fileBuffer, 0, count);
}
total += count;
System.out.println("DL count: " + count);
System.out.println("DL total: " + total);
//fileOut.write(fileBuffer, 0, count);
} catch (IOException e) {
System.out.println("Failed to download file.");
e.printStackTrace();
} finally {
try {
fileOut.flush();
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Download complete.");
Thread.currentThread().interrupt();
}
};
return run;
}
If you have any ideas as to what the problem is, I'd love to hear them. I can also try and set up a Git for the entire project if you need to see more to help. Any help is appreciated, I'm still just beginning to learn java.
Upvotes: 0
Views: 65
Reputation: 4377
The problem is you are not reading and sending the last part of your file, because of the condition in your while loop:
This condition do not allow the last part to be read from your source file and to be send. change the == 8192
part to > 0
to let the last part send.
Also you should change this condition in the dlFile
method.
Good Luck.
Upvotes: 1
Reputation: 5463
The typical idiom for reading through a file is:
byte[] fileBuffer = new byte[8192];
while ((count = fileStream.read(fileBuffer)) > 0) {
// Do something with count bytes from the fileBuffer
}
If a file has less number of bytes it gives that number of bytes and returns -1 at EOF
.
Upvotes: 1
Reputation: 196
It looks like you're missing sending the tail end of the file. In your while loop on line 12, when you send the last part of the file, it will be less than 8192 bytes, unless the file was a direct multiple of 8192 bytes long. You're going to need to add in some code to handle this fence post problem. When you read in the final (file.length() % 8192) bytes, count is not equal to 8192, so the while loop does not execute. This means that the data is never written to the buffer.
I think if you did a comparison on the two pictures, the received one is missing the last (file.length() % 8192) bytes.
Upvotes: 1