2013-09-26 19 views
0

我想在下面的代码的第一个例子中做这样的事情,这是非阻塞的,但它给出了损坏的文件。第二个例子工作正常,但它阻塞,如果你不关闭客户端(另一端)的输出流套接字,这是服务器连接的另一个设备,那么它将阻塞,线程执行不会比这更远。为什么这个简短的套接字代码样本产生损坏的文件?

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

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

​​

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

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

回答

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

正如你所看到的,它几乎等同于你的第二个例子,你说的“块”。

+0

在这两种情况下,偏移参数都是错误的,并且会导致它们用于抛出'ArrayIndexOutOfBoundsException'的方法。 – EJP

+0

是否发生这取决于缓冲区的大小。如果OP想要获取内存中读取和写入数据的副本,则可以这样做。但必须小心*创建足够大的缓冲区以保存传输的数据。 – Joni

+0

是否发生这种情况取决于缓冲区的大小*和文件的大小。使用'totalBytesRead'而不是零,这只是缓冲区中以前字节的大量浪费。给定一个足够大的文件,代码变得完全不可行,除非你使用整个缓冲区,通过零偏移量。捍卫这一点毫无意义,这只是错误的,而OP代码中的另一个错误应该是被挑选出来的。 – EJP

1
  1. bytesRead == -1试验应先写,不遵循它。
  2. write()的长度参数应为bytesRead
  3. read()write()的偏移参数应为零。
相关问题