2014-01-20 93 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); 
}