2012-02-11 131 views
0

我正在從網絡上下載數據庫,大小介於100千字節和500千字節之間。這裏是我的代碼(刪除無用代碼):FileOutputStream真的很慢

URLConnection uConnection = downloadUrl.openConnection(); 
InputStream iS = uConnection.getInputStream(); 
BufferedInputStream bIS = new BufferedInputStream(iS); 
byte[] buffer = new byte[1024]; 
FileOutputStream fOS = new FileOutputStream(db); 
int bufferLength = 0; 
while ((bufferLength = bIS.read(buffer)) > 0) { 
fOS.write(buffer, 0, bufferLength); 
} 
fOS.close(); 

我的問題是,他需要很長時間才能完成while語句。我把代碼搞亂了嗎?對於這樣的小文件不應該花那麼長時間,不是嗎?我在談論1分鐘,三個文件不超過1 MB ...預先感謝!

+2

什麼讓你覺得這個問題是'FileOutputStream'?這個問題可能很容易被帶寬下載資料。你用過類似Traceview來確定你正在花費的地方 你的時間? – CommonsWare 2012-02-11 16:40:55

+0

我不知道Traceview是什麼。我調試了代碼,這是因爲while語句它非常慢。我也認爲,當我的InputStream-Object被實例化時,數據的下載就完成了。還是不是在那裏下載的? – ezcoding 2012-02-11 16:44:53

+0

使用緩衝區大小1024是恕我直言,一個壞主意。在智能手機中,所有媒體通常具有4096字節或更大的塊大小(例如SD卡)。 – Robert 2012-02-11 16:49:58

回答

4

「慢」真的很模糊。這就是說,考慮你想要做什麼,你不應該使用BufferedInputStream,你的buffer太小了。

的緩衝包裝是用於優化小的讀/寫。由於您所做的只是儘可能快地讀取大量數據,因此您應該直接從InputStream中讀取數據,並使用大緩衝區(例如,64k,因爲底層本機代碼可能會在該處大塊大小)。

byte[] buffer = new byte[65536]; 
... 
while ((bufferLength = iS.read(buffer, 0, buffer.length) > 0) { 
    ... 
+0

我會嘗試。有關於Java I/O的良好在線文獻嗎?它有點讓我很困惑:) – ezcoding 2012-02-11 16:59:01

+1

我不得不穀歌周圍,但這不是特定於Java。想想這樣 - 如果你必須把一堆水從一個地方移到另一個地方,那會更快;使用16盎司杯子還是5gal桶子?有了這個小緩衝區,你不得不填充和清空它很多次,這是有成本的。當你知道你將需要一堆水時,緩衝包裝紙是用來做的,但一次只想處理一杯水。它預取桶並讓你從中取出杯滿。當水桶是空的時候,它會補充它。 – 2012-02-11 17:07:27

+0

好吧,謝謝:) – ezcoding 2012-02-11 17:17:11

-3

我發現在jdk的1.7真正的解決方案,這是由可靠,快速,簡單的製作和幾乎明確將產生於可惜面紗舊的java.io solutions.Despite網絡仍然是充足充分利用在輸入/輸出流,我會warmely建議大家使用一個簡單的方法在Java中複製文件的例子:java.nio.Files.copy(路徑起點,路徑目的地)可選參數更換目的地,遷移元數據文件屬性,甚至嘗試文件的事務性移動(如果基礎OS允許的話)。這是一份非常好的工作,等待了這麼久!您可以輕鬆地從副本(file1文件,文件文件2)通過附加一個「.toPath()」的文件實例轉換代碼(例如file1.toPath(),file2.toPath()進行說明,布爾方法isSameFile(file1.toPath(),file2.toPath()),已經使用上述複製方法裏面,但你想要任何情況下輕鬆使用。對於每一個情況下,你不能使用社區圖書館升級到1.7從阿帕奇(公共-IO)或谷歌(番石榴公地)仍建議。

+2

這與從套接字讀取數據並寫入它有什麼關係一份文件? – 2012-02-17 15:13:10