2013-11-28 94 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()'方法中,如上所示。