How does one display progress of a file copy operation in Java. without using Swing e.g. in a Web app?
Asked Answered
P

2

6

I have a web application which needs to perform a file copy operation and show user a progress bar.

Currently, the copy is being done by calling cpio which cannot give progress to the Java code until after the operation has completed. While it would be possible to use Java to monitor the number of bytes written vs. number of bytes read for an estimate of the copy progress, I think there might be a simpler solution if I code the actual copy operation in Java. I would still use cpio for archiving purposes, but the actual copy would be performed by a Java class.

Most of the help I found in my searching was related to progressMonitor, which incorporates a swing component, and I'm not sure that it can do what I want. All I need is an integer/double of the progress which I can feed to my web application's progress bar component as a % out of 100.

Prince answered 24/6, 2012 at 23:53 Comment(2)
@BalusC: The problem isn't having a progress bar widget (component, if you insist). The problem is using cpio to copy the file - progress on the copy isn't being periodically reported back to the java code, so the java code doesn't have any idea how long it will take until after cpio has already done its thing.Muskogean
BalusC, I apoligize if I wasn't clear. The ICEfaces progress bar component you linked to requires an integer from 0 - 100 in order to show progress. I already have the progress bar, but right now I need some way of getting that integer so I can feed it to the 'value' attribute of the progress bar component/widget.Prince
C
8

Here is how to copy a file in java and monitor progress on the commandline:

import java.io.*;

public class FileCopyProgress {
    public static void main(String[] args) {
        System.out.println("copying file");
        File filein  = new File("test.big");
        File fileout = new File("test_out.big");
        FileInputStream  fin  = null;
        FileOutputStream fout = null;
        long length  = filein.length();
        long counter = 0;
        int r = 0;
        byte[] b = new byte[1024];
        try {
                fin  = new FileInputStream(filein);
                fout = new FileOutputStream(fileout);
                while( (r = fin.read(b)) != -1) {
                        counter += r;
                        System.out.println( 1.0 * counter / length );
                        fout.write(b, 0, r);
                }
        }
        catch(Exception e){
                System.out.println("foo");
        }
    }
}

You would have to somehow update your progress bar instead of the System.out.println(). I hope this helps, but maybe i did not understand your question.

Cicala answered 25/6, 2012 at 2:12 Comment(2)
You understood completely. I'll just convert that decimal to a whole integer and link it to the value property of my ice:outputProgress component. This works as advertised. Thanks.Prince
You do not close file streams! It makes a problem for my programNaiad
P
1

Basically, you should use a listener pattern. In this example the listener has a single method to accept the # of bytes which were just written. It could be pre-populated with the total file size to calculate a percentage to show on the screen.

ReadableByteChannel source = ...;
WritableByteChannel dest = ...;
FileCopyListener listener = ...;


ByteBuffer buf = ByteBuffer.allocateDirect(BUFFER_SIZE);
while (src.read(buf) != -1) {
  buf.flip();
  int writeCount = dest.write(buf);
  listener.bytesWritten(writeCount);
  buf.compact();
}
buf.flip();
while (buffer.hasRemaining()) {
  int writeCount = dest.write(buf);
  listener.bytesWritten(writeCount);
}
Prolepsis answered 25/6, 2012 at 3:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.