Java I/O How to - Monitor progress of FileChannels transferFrom() method








Question

We would like to know how to monitor progress of FileChannels transferFrom() method.

Answer

/*from   w w w  .j  a  v a 2s.  c o  m*/
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class Main  implements ProgressCallBack{
  public static void main(String[] args) {
    new Main("c:/a/data.dat", "http://your server.com/index.htm");
  }
  public Main(String localPath, String remoteURL) {
    FileOutputStream fos;
    ReadableByteChannel rbc;
    URL url;
    try {
      url = new URL(remoteURL);
      rbc = new CallbackByteChannel(Channels.newChannel(url.openStream()),
          contentLength(url), this);
      fos = new FileOutputStream(localPath);
      fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public void callback(CallbackByteChannel rbc, double progress) {
    System.out.println(rbc.getReadSoFar());
    System.out.println(progress);
  }
  int contentLength(URL url) {
    HttpURLConnection connection;
    int contentLength = -1;
    try {
      connection = (HttpURLConnection) url.openConnection();
      contentLength = connection.getContentLength();
    } catch (Exception e) {
    }
    return contentLength;
  }
}
interface ProgressCallBack {
  public void callback(CallbackByteChannel rbc, double progress);
}


class CallbackByteChannel implements ReadableByteChannel {
  ProgressCallBack delegate;
  long size;
  ReadableByteChannel rbc;
  long sizeRead;

  CallbackByteChannel(ReadableByteChannel rbc, long expectedSize,
      ProgressCallBack delegate) {
    this.delegate = delegate;
    this.size = expectedSize;
    this.rbc = rbc;
  }
  public void close() throws IOException {
    rbc.close();
  }
  public long getReadSoFar() {
    return sizeRead;
  }

  public boolean isOpen() {
    return rbc.isOpen();
  }

  public int read(ByteBuffer bb) throws IOException {
    int n;
    double progress;
    if ((n = rbc.read(bb)) > 0) {
      sizeRead += n;
      progress = size > 0 ? (double) sizeRead / (double) size
          * 100.0 : -1.0;
      delegate.callback(this, progress);
    }
    return n;
  }
}