2011-07-06 131 views
2

我的應用程序無法通過套接字連接正確傳輸數據並將其正確寫入文件。超過65,535字節的文件被損壞,不再被設計運行它們的程序識別。如何正確寫入文件數據?

我已經能夠成功發送小的.doc和.txt文件,但.mp3 .wmv .m4a .avi和其他任何內容都無法正常工作。大文檔也沒有。

我已經找遍了互聯網尋找解決這個問題的方法。我已經反覆調整了I/O代碼來解決這個問題,但它仍然不起作用!這是處理髮送和接收文件的超類中的I/O代碼。如果您需要更多信息/其他代碼部分,請告訴我。

protected void sendFile() throws IOException { 
    byte[] bytes = new byte[(int) file.length()]; 
    buffin = new BufferedInputStream(new FileInputStream(file)); 
    int bytesRead = buffin.read(bytes,0,bytes.length); 
    System.out.println(bytesRead); 
    out = sock.getOutputStream(); 
    out.write(bytes,0,fileBytes); 
    out.flush(); 
    out.close(); 
} 

protected void receiveFile() throws IOException { 
    byte[] bytes = new byte[fileBytes]; 
    in = sock.getInputStream(); 
    for(int i=0;i<fileBytes;i++) { 
     in.read(bytes); 
    } 
    fos = new FileOutputStream("/Datawire/"+fileName); 
    buffout = new BufferedOutputStream(fos); 
    buffout.write(bytes,0,fileBytes); 
    buffout.flush(); 
    buffout.close(); 
} 

更新的代碼(即工作):

protected void sendFile() throws IOException { 
    if((file.length())<63000) { 
     byte[] bytes = new byte[(int)file.length()]; 
     buffin = new BufferedInputStream(new FileInputStream(file)); 
     buffin.read(bytes,0,bytes.length); 
     out = sock.getOutputStream(); 
     out.write(bytes,0,bytes.length); 
     out.close(); 
    } else { 
     byte[] bytes = new byte[32000]; 
     buffin = new BufferedInputStream(new FileInputStream(file)); 
     out = sock.getOutputStream(); 
     int bytesRead; 
     while((bytesRead = buffin.read(bytes))>0) { 
      out.write(bytes,0,bytesRead); 
     } 
     out.close(); 
    } 
} 

protected void receiveFile() throws IOException { 
    if(fileBytes<63000) { 
     byte[] bytes = new byte[32000]; 
     in = sock.getInputStream(); 
     System.out.println(in.available()); 
     in.read(bytes,0,fileBytes); 
     fos = new FileOutputStream("/Datawire/"+fileName); 
     buffout = new BufferedOutputStream(fos); 
     buffout.write(bytes,0,bytes.length); 
     buffout.close(); 
    } else { 
     byte[] bytes = new byte[16000]; 
     in = sock.getInputStream(); 
     fos = new FileOutputStream("/Datawire/"+fileName); 
     buffout = new BufferedOutputStream(fos); 
     int bytesRead; 
     while((bytesRead = in.read(bytes))>0) { 
      buffout.write(bytes,0,bytesRead); 
     } 
     buffout.close(); 
    } 
} 
+2

接收器如何知道要讀取多少字節?似乎你錯過了那個。您假定大小,直到滿足大小,然後將文件寫入磁盤。 –

+0

@Rob_Goodwin請注意發送文件之前運行的發送和接收信息方法。諸如文件名和文件大小的信息被髮送到那裏的接收端。文件大小由接收器的變量fileBytes表示。 – bgroenks

回答

1

你的代碼是完全錯誤的。這是如何複製Java中的流:

int count; 
byte[] buffer = new byte[8192]; // more if you like but no need for it to be the entire file size 
while ((count = in.read(buffer)) > 0) 
{ 
    out.write(buffer, 0, count); 
} 

您應該在發送文件時以及接收文件時使用它。目前你的發送方法希望整個文件適合內存;符合INTEGER_MAX字節;並通過讀取方法在一個塊中讀取,而無需檢查結果。你不能承擔任何這些事情。你的接收方法是完全垃圾:它只是覆蓋相同的數組,而不檢查任何read()結果。

編輯:您的修改代碼一樣糟糕,或更糟。您正在調用read()來檢查EOS,然後拋出該字節,然後再次調用read()並拋出它返回的讀取計數。你毫無意義地有一個不同的文件路徑< 64000或63000,或任何它是沒有任何好處,除了給你兩個代碼路徑來測試,或者可能四個,而不是一個。無論如何,網絡一次最多隻能給你1460字節,所以有什麼意義呢?您已經擁有(a)BufferedInputStream,其默認buffersize爲8192,(b)我的代碼使用任意大小的byte []緩衝區。上面的代碼適用於兩行可執行代碼中的任意數量的數據。你的20。QED。

+0

恩,恩......謝謝你的幫忙?有點苛刻,但...我不是超級有經驗的I/O。我一直在玩各種形式的發送和接收。 – bgroenks

+0

那麼這是打算讓你的注意;-) – EJP

+0

公平的。你能解釋一下嗎?我在我的代碼中嘗試過,它不起作用。輸入仍然沒有讀取所有的字節。 – bgroenks

0

你必須考慮到InputStream.read返回字節讀取數量可能小於文件中的字節總數。

你可能會更好,只是讓像CopyUtils.copy這樣的東西爲你照顧。

2

問題是你只發送它的大塊。也就是說,你只發送了64k的文件。如果文件比64k大,那麼另一端永遠不會看到它。

想要連續讀取BufferedInputStream,直到read()返回小於-1的長度。

+0

@John_V。你指的是哪部分代碼?哪個BufferedInputStream? – bgroenks

1

我建議你使用一些好的庫來讀寫文件內容以及套接字讀/寫。例如Apache Commons IO。如果你自己堅持寫作代碼,一次只做更小的塊,而不是整個文件。

0

您需要循環直到bytesRead < 0.您需要確保fileBytes =>比傳輸的文件。

protected void receiveFile() throws IOException { 
    byte [] bytes = new byte [fileBytes]; 
    InputStream is = sock.getInputStream(); 
    FileOutputStream fos = new FileOutputStream("/Datawire/"+fileName); 
    BufferedOutputStream bos = new BufferedOutputStream(fos); 

    int bytesRead = is.read(bytes,0,bytes.length); 
    int current = bytesRead; 

    do { 
     bytesRead = 
      is.read(bytes, current, (bytes.length-current)); 
     if(bytesRead >= 0) current += bytesRead; 
    } while(bytesRead > -1); 

    bos.write(bytes, 0 , current); 
    bos.flush(); 
    bos.close(); 

} 
+0

fileBytes是文件包含的確切字節數...... – bgroenks

+0

@ ghostsoldier23,我的解決方案將使用* current *作爲實際長度寫入接收的數據。所以即使filesBytes更大,也只會寫入接收到的數據。 – RealHowTo