ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java文件传输客户端未读取所有字节

2019-10-28 03:00:40  阅读:120  来源: 互联网

标签:sockets file-io java


这个问题已经在这里有了答案:            >            Java multiple file transfer over socket                                    2个
我有一个文件发送者和接收者.在互联网上找到的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");

这是发件人的输出

Sending File: D:\Users\Administrator\Documents\AAAAAAAAAAAAAAAAAAAAAAAAAAA.avi
File Size: 54236160
Sending File…
8192
Sending File…
16384
………………..some time later
Sending File…
54231040
Sending File…
54236160
File Sent

最后一个数字54236160是发送文件的确切大小.现在,这是接收器端的最后一行.

Writing file…
54234710

因此,对于此特定文件,它始终以该大小停止,因此,由于未发送整个文件,因此接收方永远不会停止等待数据.我不了解发送方如何发送正确数量的数据,但是接收方却无法获得全部信息.我从没有在接收方看到“文件已接收”,并且接收方读取的数据量永远不会等于发送的数据量.

我发送的任何文件都会出现此问题,如果我发送的文件非常小,例如字节而非kb的文件,则接收方完全看不到任何“ Writing File …”,几乎就像它只是忽略了流.

但是互联网上的每个帖子都说这是发送文件的正确方法.哦,如果我关闭了发送套接字和/或流,由于客户端和服务器还有其他需要做的事情,我不想这样做,那么它还是无法解决问题.

我注意到的另一件事是,虽然发送方总是似乎指示其将全部金额写入缓冲区(“ total”始终为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);

解决方法:

您不应尝试读取比预期更多的数据.您的循环应为:

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

标签:sockets,file-io,java
来源: https://codeday.me/bug/20191028/1949444.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有