[英]track progress of copying files
我試圖跟蹤壓縮進度的進度。 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設備上創建類似於進度條的東西)。 所以這更像是一個架構問題。 關於如何解決的任何想法?
我同時通過添加接口作為參數來覆蓋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;
但這根本不給我任何輸出
您應該在AsyncTask中實現復制機制。 它在后台線程上運行,但您可以使用publishProgress方法發布進度。 在此之后,您可以使用AsyncTask的onProgressUpdate回調在UI線程上處理這些事件。
@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();
}
}
我對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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.