how to stop copy of a large file
-
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 }
-
- separate slot method that sets a sentinel value stopTransfer
- check value of stopTransfer in your copy loop.
- 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.
-
@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.
-
@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 indstFile.write()
/dstFile.flush()
. If really not go look atstd::ofstream
docs. Set to "unbuffered", at least to check. You may not needstd::ofstream
at all if yoursegmentSize
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.
-
@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.
-
@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.
-
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.