2014-02-10 41 views
2

嗨我有一個腳本,下載是從網絡上的文件,並在這樣做時打印出進度。問題是打印出進度的行會減慢程序的執行速度,有沒有辦法阻止它?Java程序由打印行減慢

import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.net.URL; 


public class download { 
public static void main(String[] args) { 
    try{ 
     URL u = new URL("http://upload.wikimedia.org/wikipedia/commons/1/16/Appearance_of_sky_for_weather_forecast,_Dhaka,_Bangladesh.JPG"); 
     FileOutputStream fos = new FileOutputStream("C://Users/xxx/Desktop/test.jpg"); 
     InputStream is = u.openStream(); 

     long size = u.openConnection().getContentLengthLong(); 
     int data; 
     long done = 0; 
     while((data = is.read())!=-1){ 
      double progress = (double) (done)/(double)(size)*100; 
      System.out.println(progress); // if we dont do this then then it completes fast 
      fos.write(data); 
      done++; 
     } 
     fos.close(); 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 
} 

回答

2

試着只打印出每個第x個循環。

if(done % 10 == 0) System.out.println(progress); 
+0

這是唯一的方法嗎?我以爲我可以使用線程來解決問題? – user550

+1

我確定有其他人,但線程顯示在控制檯應用程序的進展可能是過量的 –

+0

K.I.S.S,直到它需要更少S –

1

可以打印線只有(done % 100 == 0)讓我們說。

此外,您可以使用緩衝方式閱讀,這將加快程序。

+0

或許將類命名? BufferedReader –

+1

@SimonTrewhella OP可以保持相同的類,但使用不同的方法。 http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read%28byte[]%29 –

+0

好的,公平點 –

1

建議:不要在循環的每次迭代中打印進度。使用一個計數器,決定一個合理的頻率,用一個數字來修改計數器,並以該選定的頻率打印進度。

2

首先,每個I/O操作都需要很高的成本。現在,您正在爲每個讀取的字節打印一條消息(在InputStream#read中註明)。

如果您想要/需要打印進度,請執行一堆讀取的KB,通常每4 KB。您可以使用byte[] buffer來讀取和寫入數據流中的數據。

BufferedInputStream input = null; 
BufferedOutStream output = null; 
final int DEFAULT_BUFFER_SIZE = 4 * 1024; 
try { 
    input = new BufferedInputStream(is, DEFAULT_BUFFER_SIZE); 
    output = new BufferedOutputStream(fos, DEFAULT_BUFFER_SIZE); 

    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 
    int length; 
    while ((length = input.read(buffer)) > 0) { 
     output.write(buffer, 0, length); 
     done += length; 
     double progress = (double) (done)/(double)(size)*100 
     System.out.println(progress); 
    } 
} catch (IOException e) { 
    //log your exceptions... 
} finally { 
    closeResource(output); 
    closeResource(input); 
} 

而且有這個closeResource方法:

public void closeResource(Closeable resource) { 
    if (resource != null) { 
     try { 
      resource.close(); 
     } catch (IOException e) { 
      logger.error("Error while closing the resource.", e); 
     } 
    } 
} 
+0

如果沒有異常,或者不能保證文件完整,至少關閉「輸出」會很好。 – zapl

+0

@zapl我的代碼不完整且具有誤導性。更新了答案。 –

+0

@ user550我相信這是正確的答案。我的答案解決了你的症狀,但是這個可以治癒你的問題。 –