2013-11-28 84 views
0

我试图通过套接字发送大文件。该程序适用于小文件(如html页面或pdf),但是当我发送超过3/4 mb的文件时,输出总是被损坏(使用文本编辑器查看它,我注意到最后几行总是丢失)。通过套接字发送大文件时出错

这里是服务器的代码:

BufferedInputStream in = null; 
    FileOutputStream fout = null; 
    try { 
     server = new ServerSocket(port); 

     sock = server.accept(); 
     in = new BufferedInputStream(sock.getInputStream()); 

     setPerc(0); 

     received = 0; 

     int incByte = -1; 
     fout = new FileOutputStream(path+name, true); 
     long size = length; 
     do{ 
      int buffSize; 
      if(size >= 4096){ 
       buffSize = 4096; 
      }else{ 
       buffSize = 1; 
      } 
      byte[] o = new byte[buffSize]; 
      incByte = in.read(o, 0, buffSize); 
      fout.write(o); 

      received+=buffSize; 
      setPerc(calcPerc(received, length)); 
      size -= buffSize; 
      //d("BYTE LETTI => "+incByte); 
     }while(size > 0); 
     server.close(); 
    } catch (IOException e) { 
     e("Errore nella ricezione file: "+e); 
    }finally{ 
     try { 
      fout.flush(); 
      fout.close(); 
      in.close(); 
     } catch (IOException e) { 
      e("ERRORE INCOMINGFILE"); 
     } 
    } 
    pr.release(port); 

而这里的客户端代码:

FileInputStream fin = null; 
    BufferedOutputStream out = null; 
    try { 
     sock = new Socket(host, port); 

     fin = new FileInputStream(file); 
     out = new BufferedOutputStream(sock.getOutputStream()); 

     long size = file.length(); 
     int read = -1; 
     do{ 
      int buffSize = 0; 
      if(size >= 4096){ 
       buffSize = 4096; 
      }else{ 
       buffSize = (int)size; 
      } 

      byte[] o = new byte[buffSize]; 
      for(int i = 0; i<o.length;i++){ 
       o[i] = (byte)0; 
      } 
      read = fin.read(o, 0, buffSize); 
      out.write(o); 
      size -= buffSize; 
      //d("BYTE LETTI DAL FILE => "+read); 
     }while(size > 0); 
    } catch (UnknownHostException e) { 
    } catch (IOException e) { 
     d("ERRORE NELL'INVIO DEL FILE: "+e); 
     e.printStackTrace(); 
    }finally{ 
     try { 
      out.flush(); 
      out.close(); 
      fin.close(); 
     } catch (IOException e) { 
      d("Errore nella chiusura dei socket invio"); 
     } 
    } 

我觉得它的东西与缓冲区的大小有关,但我想不出这里有什么问题。

+0

永远不要依赖'File.length()'提供的文件大小,而只是继续阅读直到完成。应该使用'File.length()'作为它可能有多大的概念。 –

回答

3

这是不正确的:

 byte[] o = new byte[buffSize]; 
     incByte = in.read(o, 0, buffSize); 
     fout.write(o); 

您正在阅读高达buffSize字节,然后写正是buffSize字节。

你在另一端做同样的事情。

您可以从文件读取时逃脱。但是,当你从一个套接字读那么read容易给你一个部分填充缓冲,尤其是在书写端不能始终保持在阅读结束之前',因为你正在用大量转移来锤击网络。

做正确的做法是:

 incByte = in.read(o, 0, buffSize); 
     fout.write(o, 0, incByte); 

1 - 已经发现,当你从本地文件读取,一个read通话将通常给你所有的字节是你要求(受文件大小等的影响)。因此,如果您将buffSize设置为文件的长度,则此代码可能在从本地文件读取时有效。但是这样做是一个坏主意,因为你依赖的行为不受Java或典型操作系统的保证。

+0

谢谢,它的工作原理! – giuse

0

您可能有问题,例如这里。

read = fin.read(o, 0, buffSize); 
out.write(o); 

这里阅读给你,你实际上已经刚刚读的字节数。 在下一行中,您应该只写出与读取的字节数相同的字节数。

换句话说,你不能指望 你正在阅读是多你的缓冲区大小的文件的大小。

查看您的服务器代码也是同样的问题。

0

在Java中复制流的正确的方法是如下:

while ((count = in.read(buffer)) > 0) 
{ 
    out.write(buffer, 0, count); 
} 

其中countint,bufferbyte[]数组长度> 0,一般为8K的。您不需要在循环内分配字节数组,并且不需要特定大小的字节数组。具体而言,分配与文件一样大的缓冲区是完全浪费空间的;它只适用于Integer.MAX_VALUE字节的文件,并没有扩展。

您确实需要保存'read()'返回的计数,并将其用于'write()'方法中,如上所示。