2014-01-20 144 views
2

我正在嘗試跟蹤壓縮進度的進度。 ATM我這樣做是這樣的:跟蹤複製文件的進度

public static void compressGzipTest(final OutputStream os, final File source) throws CompressorException, 
      IOException 
    { 
     final CountingInputStream cis = new CountingInputStream(new FileInputStream(source)); 
     final GzipCompressorOutputStream gzipOut = (GzipCompressorOutputStream) new CompressorStreamFactory() 
       .createCompressorOutputStream(CompressorStreamFactory.GZIP,os); 

     new Thread() { 
      public void run() 
      { 
       try 
       { 
        long fileSize = source.length(); 

        while (fileSize > cis.getBytesRead()) 
        { 
         Thread.sleep(1000); 
         System.out.println(cis.getBytesRead()/(fileSize/100.0)); 
        } 
       } 
       catch (Exception ex) 
       { 
        ex.printStackTrace(); 
       } 
      } 
     }.start(); 

     IOUtils.copy(cis,gzipOut); 
    } 

這工作得很好,但我需要的螺紋,它提供有關不以這種方法來實現進度的反饋,但稱這是(爲了創造東西的時候就像android設備上的進度條)。所以這更像是一個架構問題。任何想法,關於如何解決?

回答

1

您應該在AsyncTask中實現複製機制。 它在後臺線程上運行,但您可以使用publishProgress方法發佈進度。 之後,您可以在UI線程上使用onProgressUpdate回調AsyncTask來處理這些事件。

 @Override 
     protected void onProgressUpdate(final Double... values) { 
      super.onProgressUpdate(values); 
      //... 
     } 

編輯: 示例:

 final byte[] buf = new byte[1024]; 
     try { 
      int bufferSize; 
      final int size = inputStream.available(); 

      long alreadyCopied = 0; 
      while ((bufferSize = inputStream.read(buf)) > 0 && canRun.get()) { 
       alreadyCopied += bufferSize; 
       outputStream.write(buf, 0, bufferSize); 
       publishProgress(1.0d * alreadyCopied/size); 
      } 
     } catch (final IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       outputStream.flush(); 
       outputStream.getFD().sync(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
+0

我解決它的時刻通過傳遞InputStream作爲參數。但是我是否正確地做到了這一點,publishProgress/onProgressUpdate會默認處理我方法的進度,還是必須實施如何接收進度反饋? – JohnPlata

+0

請看我編輯的答案,在那裏你可以看到一個關於它的例子。 – R4ng3LII

2

我同時通過添加一個接口作爲參數經由覆蓋IOUtils.copy()解決了它:

public static long copy(final InputStream input, final OutputStream output, int buffersize, 
     ProgressListener listener) throws IOException 
{ 
    final byte[] buffer = new byte[buffersize]; 
    int n = 0; 
    long count = 0; 
    while (-1 != (n = input.read(buffer))) 
    { 
     output.write(buffer,0,n); 
     count += n; 
     listener.onProgress(n); 
    } 
    return count; 
} 

然後由稱爲像這樣的東西

copy(input, output, 4096, new ProgressListener() { 

       long totalCounter = 0; 

       DecimalFormat f = new DecimalFormat("#0.00"); 

       @Override 
       public void onProgress(long bytesRead) 
       { 
        totalCounter += bytesRead; 
        System.out.println(f.format(totalCounter/(fileSize/100.0))); 
       } 
      }); 

我現在面臨的唯一挑戰是限制控制檯上的輸出,而不是每個字節[4096],但是讓我們說每兩兆字節。我想是這樣的:

while (-1 != (n = input.read(buffer))) 
    { 
     output.write(buffer,0,n); 
     count += n; 
     while(n % 2097152 == 0) 
     { 
      listener.onProgress(n); 
     } 
    } 
    return count; 

但是,這並沒有給我任何輸出

1

我有一個非常類似的解決方案,以通過JohnPlata提出的一個。我從IOUtils中採納了copy方法,並添加了兩個參數:要複製的文件的原始文件大小和用於更新進度的偵聽器。我的副本發生在解壓.gz文件時,由於解壓後的文件大約比打包文件大3倍,我估計最終結果文件大小(因此行copy(in, out, inputFile.length()*3, progressListener);)。整個事情是基於Android的,所以Listener會根據進度更新通知。

public static File unGzip(final File inputFile, final File outputDir, ProgressListener progressListener) 
     throws FileNotFoundException, IOException { 
    final File outputFile = new File(outputDir, inputFile.getName() 
      .substring(0, inputFile.getName().length() - 3)); 
    final GZIPInputStream in = new GZIPInputStream(new FileInputStream(inputFile)); 
    final FileOutputStream out = new FileOutputStream(outputFile); 
    copy(in, out, inputFile.length()*3, progressListener); 
    in.close(); 
    out.close(); 
    return outputFile; 
} 

public static long copy(InputStream input, OutputStream output, long inputfilesize, 
         ProgressListener progressListener) 
     throws IOException { 
    byte[] buffer = new byte[8024]; 
    boolean n = false; 
    long percent = 0; 
    long count; 
    int n1; 
    for(count = 0L; -1 != (n1 = input.read(buffer)); count += (long)n1) { 
     output.write(buffer, 0, n1); 
     if ((count*100)/inputfilesize > percent) { 
      percent = (count*100)/inputfilesize; 
      progressListener.onProgressUpdate((int)percent); 
     } 
    } 
    return count; 
} 

,所有的這就是所謂的類的代碼如下所示:

File ungzippedFile = Util.unGzip(movedFile, offlineDataDirFile, new ProgressListener() { 
    @Override 
    public void onProgressUpdate(int percentage) { 
     notificationBuilder.setProgress(100, percentage, false); 
     notificationManagerCompat.notify(1, notificationBuilder.build()); 
    } 
}); 

此類還包含接口:

public interface ProgressListener { 
    void onProgressUpdate(int percentage); 
}