Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. how to stop copy of a large file
QtWS25 Last Chance

how to stop copy of a large file

Scheduled Pinned Locked Moved Unsolved C++ Gurus
7 Posts 3 Posters 689 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JoeCFD
    wrote on 24 Jun 2024, 13:22 last edited by
    #1

    The following code is to copy a large file in segments. The goal is to stop copy when the user presses a cancel button.
    However, what the code does is to copy all data quickly to dstFile and write the data to disk all in once in call srcFile.close();
    How to handle cancellation of a large file copy? Any ideas?

    void copyFileInSegments(const std::string& srcFilename, const std::string& dstFilename, std::size_t segmentSize)
     {
        std::ifstream srcFile(srcFilename, std::ios::binary);
        if (!srcFile.is_open()) {
            std::cerr << "Error: Could not open source file " << srcFilename << std::endl;
            return;
        }
    
        std::ofstream dstFile(dstFilename, std::ios::binary);
        if (!dstFile.is_open()) {
            std::cerr << "Error: Could not open destination file " << dstFilename << std::endl;
            srcFile.close();
            return;
        }
    
        std::vector<char> buffer(segmentSize);
        std::size_t totalBytesCopied = 0;
    
        while (srcFile) {
            srcFile.read(buffer.data(), segmentSize);
            std::streamsize bytesRead = srcFile.gcount();
            if (bytesRead > 0) {
                dstFile.write(buffer.data(), bytesRead);
                dstFile.flush(); // Flush the buffer to ensure data is written to disk
    
                totalBytesCopied += bytesRead;
                std::cout << "Copied " << bytesRead << " bytes, total " << totalBytesCopied << " bytes." << std::endl;
            } else {
                std::cout << "No bytes read, possibly end of file or error." << std::endl;
            }
    
            if (cancelCopy.load()) {
                std::cout << "File copy was cancelled.\n";
                break;
            }
        }
    
        if (!cancelCopy.load()) {
            std::cout << "File copy completed successfully. Total bytes copied: " << totalBytesCopied << std::endl;
        }
    
        // Flush again before closing (for diagnostic purposes)
        dstFile.flush();
        std::cout << "Flushed buffer before closing." << std::endl;
    
        srcFile.close();
        dstFile.close(); // Close the file
    }
    
    1 Reply Last reply
    0
    • K Offline
      K Offline
      Kent-Dorfman
      wrote on 24 Jun 2024, 17:44 last edited by Kent-Dorfman
      #2
      1. separate slot method that sets a sentinel value stopTransfer
      2. check value of stopTransfer in your copy loop.
      3. since you do the copy in a loop (without checking the event queue) you should read and process Qt events on every iteration.

      This is probly the path of least resistance solution, but there are others.

      J 1 Reply Last reply 25 Jun 2024, 15:17
      1
      • K Kent-Dorfman
        24 Jun 2024, 17:44
        1. separate slot method that sets a sentinel value stopTransfer
        2. check value of stopTransfer in your copy loop.
        3. since you do the copy in a loop (without checking the event queue) you should read and process Qt events on every iteration.

        This is probly the path of least resistance solution, but there are others.

        J Offline
        J Offline
        JoeCFD
        wrote on 25 Jun 2024, 15:17 last edited by JoeCFD
        #3

        @Kent-Dorfman
        thanks for your reply.

        dstFile.flush(); seems not doing anything in the loop. The loop is finished very quickly. dstFile looks like a buffer. Writing copied data to disk is done in dstFile.close(); This call takes long and can not be stopped. Therefore, processing events will not help. Another scenario is that a lot of small files are copied and this process can be stopped easily.

        My app will crash if the parent widget which launches the copy worker class is destroyed. One solution may be to detach the thread and let copy continue behind the scene. But this is not cancellation.

        J 1 Reply Last reply 25 Jun 2024, 17:04
        0
        • J JoeCFD
          25 Jun 2024, 15:17

          @Kent-Dorfman
          thanks for your reply.

          dstFile.flush(); seems not doing anything in the loop. The loop is finished very quickly. dstFile looks like a buffer. Writing copied data to disk is done in dstFile.close(); This call takes long and can not be stopped. Therefore, processing events will not help. Another scenario is that a lot of small files are copied and this process can be stopped easily.

          My app will crash if the parent widget which launches the copy worker class is destroyed. One solution may be to detach the thread and let copy continue behind the scene. But this is not cancellation.

          J Offline
          J Offline
          JonB
          wrote on 25 Jun 2024, 17:04 last edited by
          #4

          @JoeCFD
          I don't really understand what your question or issue is?

          You can't do a lot about the way the OS buffers and flushes and writes, and you shouldn't want to.

          I can't really believe it takes all its time in dstFile.close(), for a big file at least time should be spent in dstFile.write()/dstFile.flush(). If really not go look at std::ofstream docs. Set to "unbuffered", at least to check. You may not need std::ofstream at all if your segmentSize is of a certain size.

          If you have "big" or "slow" files you should be able to cancel out during the operation as best you can. You shouldn't have to worry about bytes which have already been sent by then. You can do the file copy in a thread if you wish if you provide a mechanism to interrupt, or you could do "chunks" at a time in the UI thread with event loop allow in between.

          J 1 Reply Last reply 25 Jun 2024, 23:02
          0
          • J JonB
            25 Jun 2024, 17:04

            @JoeCFD
            I don't really understand what your question or issue is?

            You can't do a lot about the way the OS buffers and flushes and writes, and you shouldn't want to.

            I can't really believe it takes all its time in dstFile.close(), for a big file at least time should be spent in dstFile.write()/dstFile.flush(). If really not go look at std::ofstream docs. Set to "unbuffered", at least to check. You may not need std::ofstream at all if your segmentSize is of a certain size.

            If you have "big" or "slow" files you should be able to cancel out during the operation as best you can. You shouldn't have to worry about bytes which have already been sent by then. You can do the file copy in a thread if you wish if you provide a mechanism to interrupt, or you could do "chunks" at a time in the UI thread with event loop allow in between.

            J Offline
            J Offline
            JoeCFD
            wrote on 25 Jun 2024, 23:02 last edited by
            #5

            @JonB A feature is needed to cancel copy of files with large size when a cancel button is pressed in the middle of copying.

            I do not believe dstFile.close() takes most of time for copy as well. But when the code is executed, the problem shows up. I do not have solution now and therefore look for help here.

            J 1 Reply Last reply 26 Jun 2024, 07:43
            0
            • J JoeCFD
              25 Jun 2024, 23:02

              @JonB A feature is needed to cancel copy of files with large size when a cancel button is pressed in the middle of copying.

              I do not believe dstFile.close() takes most of time for copy as well. But when the code is executed, the problem shows up. I do not have solution now and therefore look for help here.

              J Offline
              J Offline
              JonB
              wrote on 26 Jun 2024, 07:43 last edited by
              #6

              @JoeCFD said in how to stop copy of a large file:

              @JonB A feature is needed to cancel copy of files with large size when a cancel button is pressed in the middle of copying.

              I agree. And copying in "blocks" from the main thread, or copying in secondary thread with a check for interrupt, should do that. Which your code seems to do, provided your "check for cancel" works, which I don't know. And I don't know what else there is to say.

              1 Reply Last reply
              0
              • K Offline
                K Offline
                Kent-Dorfman
                wrote on 17 Jul 2024, 15:05 last edited by
                #7

                FWIW, since you are using the STL streams classes, note that you have buffer size control in the STL classes. One could weakly argue that you should use the Qt file IO methods instead of STL streams, since mixing frameworks is often the cause of problems in programming.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved