2016-04-02 68 views
1

我們在實驗室中進行了一些練習,其中一個練習是將文件傳輸方法從FileInputStream轉換爲BufferedInputStream。它是一個向Web服務器發送GET請求的客戶端,它發送請求的文件。 我想出了一個簡單的解決方案,我只是想檢查它是否正確。從FileInputStream到BufferedInputStream轉換

原始代碼:

try { 
     FileInputStream fis = new FileInputStream(req); 
     // req, String containing file name 
     byte[] data = new byte [fis.available()]; 
     fis.read(data); 
     out.write(data); // OutputStream out = socket.getOutputStream(); 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

我嘗試:

try { 
     BufferedInputStream bis = new BufferedInputStream (new FileInputStream(req)); 
     byte[] data = new byte[4]; 

     while(bis.read(data) > -1) { 
     out.write(data); 
     data = new byte[4]; 
     } 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

該文件是一個網頁,名爲index.html,其中包含一個簡單的HTML頁面。 我每次都必須重新分配數組,因爲在while循環的最後一次執行時,如果文件的大小不是4的倍數,那麼數據數組將包含前一次執行的字符,這些字符會顯示在瀏覽器中。 爲了進行調試,我選擇了4作爲數據大小。 輸出正確。

這是一個很好的解決方案還是我可以做得更好?

回答

1

每次都不需要重新創建字節數組 - 只需覆蓋它。更重要的是,你的循環內有一個概念錯誤。假設它全部有效,每次迭代只是將數組寫入流中。如果你檢查BufferedInputStream#read的文檔,你會發現它可能讀不到足夠的數據來填充整個數組,並且會返回實際讀取的字節數。你應該使用這個數字來限制你寫的字節數量:

while((int len = bis.read(data)) > -1) { 
    out.write(data, 0, len); 
} 
0

我建議你在完成後關閉你的文件。 BufferedInputStream在默認情況下使用8 KB緩衝區,您將減少到更小的緩衝區。一個更簡單的解決方案是一次複製8 KB而不使用添加的緩衝區

try (InputStream in = new FileInputStream(req)) { 
    byte[] data = new byte[8 << 10]; 
    for (int len; (len = bis.read(data)) > -1;) 
     out.write(data, 0, len); 
} catch (IOException e) { 
    out.write("404 Not Found\n".getBytes()); 
} 
+0

感謝您的答覆。在存儲在hd上的文件的情況下,FileInputStream在每次讀取操作時訪問磁盤,而BufferedInputStream不會,因此一般而言,效率更高。這是通過網絡提供文件時的情況 - 這是我現在的情況嗎?或者是基本沒有區別? –

+0

FileInputStream在每次讀取時都會訪問操作系統,操作系統可以使用預測性的預讀方式,並且每隔一段時間就會只讀取一次磁盤。 BufferedInputStream只有在你閱讀的數據塊小得多時纔會有幫助,例如<< 512字節,比它讀取的緩衝區大。即它不是魔術,它只是通過閱讀更大的緩衝區來做你已經在做的事情。 –