-1

What is the best way to monitor the progress of a copying process in Java? Currently, I'm using the following code:

currently I use :

Files.copy(new File(source).toPath(), new File(target).toPath(), StandardCopyOption.REPLACE_EXISTING);

I've tried running a file size check on a parallel thread, but this sometimes locks the target file and other times shows the full size before the process finishes. Can anyone recommend a more reliable approach?

    Thread one = new Thread() {
            public void run() {
                System.out.println("Thread start");
                while (true) {
                    try {
                        File sourceFile = new File(target);
//                      sourceFile.le
                        if (sourceFile.exists()) {
                            long bytes = Files.size(sourceFile.toPath());
                            double length = sourceFile.length()*1.0;
//                          System.out.println("Size of " + sourceFile.getName() + ": " + bytes + " bytes");
                            System.out.println(1.0 * length / sourcebytes);
//                          if (sourcebytes == bytes) {
//                              System.out.println("Copy Done");
//                              break;
//                          }
                        } else {
                            System.out.println("Source file does not exist");
                        }
                        Thread.sleep(100); // sleep for 1 second
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        one.start();

This method doesnt work because its too slow:

File filein = new File(source);
    File fileout = new File(target);
    FileInputStream fin = null;
    FileOutputStream fout = null;
    long length = filein.length();
    long counter = 0;
    int r = 0;
    byte[] b = new byte[1024];
    int lastProgress = -1; // initialize with an impossible value
    try {
        fin = new FileInputStream(filein);
        fout = new FileOutputStream(fileout);
        while ((r = fin.read(b)) != -1) {
            counter += r;
            if (counter % 1024 == 0) {
                int progress = (int) Math.round((double) counter / length * 100);
                if (progress > lastProgress) { // print only if progress has changed
                    System.out.println(progress + "%");
                    lastProgress = progress;
                }
            }
            fout.write(b, 0, r);
        }
    } catch (Exception e) {
        System.out.println("foo");
    }
SüniÚr
  • 826
  • 1
  • 16
  • 33
  • 2
    Your hand-implemented copy is not using the fastest option. Personally I'd use `FileChannels` like [in this answer](https://stackoverflow.com/a/4004874/40342) and then monitor the positions of either the input or output channel in a separate thread (according to [the doc](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/nio/channels/FileChannel.html) accessing them in multiple threads is acceptable, with some obvious restrictions). – Joachim Sauer Mar 13 '23 at 12:19

1 Answers1

0

Based on @joachim-sauer tipp I used Filechannel.

try {
        // Open input and output file streams
        FileInputStream inputFile = new FileInputStream(in);
        FileOutputStream outputFile = new FileOutputStream(out);

        // Get the channels for the input and output files
        FileChannel inputChannel = inputFile.getChannel();
        FileChannel outputChannel = outputFile.getChannel();

        // Create a buffer to hold the data
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        
        double inputSize = (double) inputChannel.size();
        
        int counter =0;

        // Read the data from the input file into the buffer
        while (inputChannel.read(buffer) > 0) {
            // Flip the buffer to prepare for writing
            buffer.flip();

            // Write the data to the output file
            outputChannel.write(buffer);
            
            // Clear the buffer to prepare for reading more data
            buffer.clear();
            counter ++;
            if(counter == 1024) {
                counter = 0;
                System.out.println((double) outputChannel.size() / inputSize);
            }
        }

        // Close the channels and streams
        inputChannel.close();
        outputChannel.close();
        inputFile.close();
        outputFile.close();

        System.out.println("File copied successfully!");
    } catch (IOException e) {
        e.printStackTrace();
    }

Thanks

SüniÚr
  • 826
  • 1
  • 16
  • 33