15

I'm using Java NIO to copy something:

Files.copy(source, target);

But I want to give users the ability to cancel this (e.g. if the file is too big and it's taking a while).

How should I do this?

spongebob
  • 8,370
  • 15
  • 50
  • 83
roim
  • 4,780
  • 2
  • 27
  • 35

2 Answers2

30

Use the option ExtendedCopyOption.INTERRUPTIBLE.

Note: This class may not be publicly available in all environments.

Basically, you call Files.copy(...) in a new thread, and then interrupt that thread with Thread.interrupt():

Thread worker = new Thread() {
    @Override
    public void run() {
        Files.copy(source, target, ExtendedCopyOption.INTERRUPTIBLE);
    }
}
worker.start();

and then to cancel:

worker.interrupt();

Notice that this will raise a FileSystemException.

spongebob
  • 8,370
  • 15
  • 50
  • 83
roim
  • 4,780
  • 2
  • 27
  • 35
  • 1
    In Java SE 8, this option is not supported in the Oracle JDK. Alternatively, consider [using a `FileChannel`](http://stackoverflow.com/a/42183069/3453226). – spongebob Feb 19 '17 at 13:01
1

For Java 8 (and any java without ExtendedCopyOption.INTERRUPTIBLE), this will do the trick:

public static void streamToFile(InputStream stream, Path file) throws IOException, InterruptedException {
    try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(file))) {
        byte[] buffer = new byte[8192];
        while (true) {
            int len = stream.read(buffer);
            if (len == -1)
                break;

            out.write(buffer, 0, len);

            if (Thread.currentThread().isInterrupted())
                throw new InterruptedException("streamToFile canceled");
        }
    }
}
Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50