Title: track progress of copying files
Tags: android;compression;progress
Question: I am trying to track the progress of a compression progress. ATM I am doing it like this:
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 &gt; cis.getBytesRead())
{
Thread.sleep(1000);
System.out.println(cis.getBytesRead() / (fileSize / 100.0));
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}.start();
IOUtils.copy(cis,gzipOut);
This works fine, but I need the thread, which is giving feedback about the progress not to be implemented in this method, but when calling it (in order to create something like a progressbar on an android device). So this is more like an architectural issue. Any ideas, on how to solve that?


Here is another answer: I meanwhile solved it via overwriting the IOUtils.copy() by adding an interface as parameter:
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;
which is then called by something like this
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)));
}
});
The only thing, i am challenged by now, is to limit the output on the console not for each byte[4096] but for let's say each two megabyte. I tried something like this:
while (-1 != (n = input.read(buffer)))
output.write(buffer,0,n);
count += n;
while(n % 2097152 == 0)
{
listener.onProgress(n);
}
return count;
But that does not give me any output at all

Here is another answer: I have a very similar solution to the one proposed by JohnPlata. I took the copy Method from IOUtils and added two parameters: the original filesize of the file to be copied from and a listener for updating the progress. My copy happens during unpacking a .gz file and since the unpacked files are roughly 3 times bigger than the packed files I estimate the end result file size (hence the line copy(in, out, inputFile.length()*3, progressListener);). The whole thing is Android-based, so the Listener updates a notification with the progress.
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 &gt; percent) {
percent = (count*100)/inputfilesize;
progressListener.onProgressUpdate((int)percent);
}
return count;
The code of the class where all of this is called looks like this:
File ungzippedFile = Util.unGzip(movedFile, offlineDataDirFile, new ProgressListener() {
@Override
public void onProgressUpdate(int percentage) {
notificationBuilder.setProgress(100, percentage, false);
notificationManagerCompat.notify(1, notificationBuilder.build());
This class also contains the interface:
public interface ProgressListener {
void onProgressUpdate(int percentage);

Here is another answer: You should implement the copy mechanism in AsyncTask.
It runs on a background thread, but you can post progress with the publishProgress method.
After this you can handle these events on the UI thread with the onProgressUpdate callback of the AsyncTask.
@Override
protected void onProgressUpdate(final Double... values) {
super.onProgressUpdate(values);
//...
}
Example:
final byte[] buf = new byte[1024];
try {
int bufferSize;
final int size = inputStream.available();
long alreadyCopied = 0;
while ((bufferSize = inputStream.read(buf)) &gt; 0 &amp;&amp; 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();
}
}
Comment for this answer: I solved it for the moment by passing the InputStream as a parameter. But do I get you right, that publishProgress/onProgressUpdate will take care of the progress of my method by default or do I still have to implement on how to receive the feedback of the progress?
Comment for this answer: Please see my edited answer, there you can see an example about it.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 3, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2014:00:01/20/14', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<android><compression><progress>', 'Title': 'track progress of copying files', 'ViewCount': 2556, 'id': 21239223, 'user_AboutMe': '<p>One of my biggest goals in life is to make a difference and generate a positive outcome in the environment I live in. Both, in terms of work and social life. I am constantly striving to improve myself and to work with others to identify and improve capabilities and skills.</p>\n<p>Colleagues and friends have described me as a motivated and a motivating person with a strong ability to identify problems, turn them into challenges and eventually resolving them. Being organized and structured, accurate and precise but also humble, generous, caring, sharing and humorous. Helping and supporting others as an excellent teacher, mentor, and leader.</p>\n<p>My philosophy is: Quality over quantity! Everything in life is worth being done with passion. This attitude is reflected throughout all of my work.</p>\n<p>Think twice, code once!</p>\n', 'user_AccountId': 3860652.0, 'user_DisplayName': 'Jonas Bausch', 'user_Reputation': 185.0, 'user_Views': 42.0, 'user_id': 3198476.0}}