我有文件发件人和收件人。从我在互联网上找到的10个左右的帖子中,这是通过Java中的套接字发送文件的正确方法。看一下下面的代码片段。
发信人:
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);
}
接收器:
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");
这是发件人的输出
发送文件:D:\ Users \ Administrator \ Documents \ AAAAAAAAAAAAAAAAAAAAAAAAAAA.avi
文件大小:54236160
发送文件...
8192
发送文件...
16384个
....................一段时间后 发送文件...
54231040个
发送文件...
54236160个
文件已发送
最后一个数字54236160是要发送的文件的确切大小。现在这是接收方的最后一行。
写文件......
54234710
因此对于这个特定的文件,它总是停在这个大小,所以因为没有发送整个文件,接收器永远不会停止等待数据。我不明白发送者如何发送正确数量的数据,但接收者并没有全部收到。我从未在接收器端看到“文件已接收”,并且接收器读取的数据量永远不会等于发送的数量。
我发送的任何文件都会出现此问题,如果我发送非常小的文件,例如字节不是kb的文件,我在接收器端看不到任何“写入文件...”,几乎就像它一样只是忽略了流。
然而,互联网上的每篇帖子都说这是发送文件的正确方法。哦,如果我关闭发送套接字和/或流,我不想做,因为客户端和服务器需要做其他事情,它仍然无法解决问题。
我注意到的另一件事是,虽然发送者似乎总是指示其写入缓冲区的全部数量(总是为“总数”的8192的倍数),但是接收者不会。
以下是获取文件大小和文件名的代码。也许这就是错误所在?在我们开始发送和接收文件之前,我没有看到它是如何完成的。
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);
答案 0 :(得分:4)
您不应该尝试读取比预期更多的数据。你的循环应该是:
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");
}
(您可以调整输出以显示您已读取的字节数,而不是您想要读取的数量,但我认为这种方法更简单。)
如果仍然没有得到你所有的数据,你应该在编写代码中刷新输出流 - 我不希望你必须这样做,但如果你没有关闭套接字,我猜它可以永远缓冲它。
如果循环终止但文件似乎不完整,请确保在所有这些之后关闭bos
。
如果 没有帮助,那么在进入此循环之前,其他东西可能已经读取了数据的开头。您应该将输出文件中的数据与原始文件进行比较。查看输出文件中的第一个(例如)16个字节,并检查它们是否在输入文件的开头。如果它们不存在,则表明问题在于您在向我们展示的代码之前使用连接进行的操作。 (例如,用于发送和接收预期文件大小的代码。)
既然我们可以看到你如何发送/接收文件大小,那肯定是问题所在。扫描仪正在读取一些文件数据。要解决此问题,只需在发送方使用DataOutputStream
,在接收方使用DataInputStream
:
DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream());
output.writeUTF(fileName);
output.writeInt(fileSize);
// Write the data as before, to output
在接收方:
DataInputStream input = new DataOutputStream(clientSocket.getInputStream());
String fileName = input.readUTF(name);
int fileSize = input.readInt();
// Read the data before, as above, from input