为什么这个简短的套接字代码样本会产生损坏的文件?

时间:2013-09-26 10:45:51

标签: java android sockets networking tcp

我正在尝试执行类似下面代码的第一个示例,即非阻塞但它会提供损坏的文件。第二个例子工作正常,但是它是阻塞的,如果你没有关闭来自客户端(另一端)的输出流的套接字,这是该服务器连接的另一个设备,那么它将阻塞并且线程执行不会比那更远了。

导致它每次都产生损坏文件的第一段代码出了什么问题?

第一个示例代码,好主意但产生损坏的文件;

 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;
            }
        }     

第二个例子,代码卡住;块。所以我不能使用它,因为你必须从客户端杀死套接字以使代码执行继续超出这些代码行。但它产生完美无损的文件。

  while((count = bufferedInputStream.read(buffer)) > 0){
        bufferedOutputStream.write(buffer, 0, count); 
 }

2 个答案:

答案 0 :(得分:1)

  1. bytesRead == -1的测试应该在写入之前,而不是遵循它。
  2. write()的长度参数应为bytesRead
  3. read()write()的偏移量参数应为零。

答案 1 :(得分:0)

该行写入所有“剩余”字节,即使只读取了一个字节,如果read返回-1表示输入结束,也可能写入一些内容:

bufferedOutputStream.write(buffer, totalBytesRead, bytesRemaining);

要仅写入已读取的字节,请将读取的字节数作为第三个参数传递。

    int bytesRead = bufferedInputStream.read(buffer, totalBytesRead, bytesRemaining);

    if (bytesRead == -1) {
        break;
     } else {
        bufferedOutputStream.write(buffer, totalBytesRead, bytesRead);
        totalBytesRead += bytesRead;
    }

没有理由为什么第二个代码应该阻止而不是这个。

另请注意,这样您就可以创建正在传输的数据的内存中副本,如果缓冲区不够大,可能会占用大量内存或使程序失败ArrayIndexOutOfBoundsException。如果这不是您的意图,则在读取和写入时应使用0而不是totalBytesRead作为数组偏移量,并将读取的字节数限制为缓冲区的大小。在这些转换之后,代码看起来像这样:

    int bytesRead = bufferedInputStream.read(buffer);

    if (bytesRead == -1) {
        break;
     } else {
        bufferedOutputStream.write(buffer, 0, bytesRead);
        totalBytesRead += bytesRead;
    }

正如您所看到的,它与您的第二个示例几乎完全相同,您说的是“阻止”。