中断文件复制和重命名操作
在需要传输大文件并且用户需要能够取消操作的情况下, Qt 提供的默认 copy() 和 rename() 方法可能会受到限制。挑战在于如何在不引入显着性能开销或用户挫败感的情况下中断这些进程。
查询 Qt 中的中断支持
在研究 QFile 文档时,很明显 Qt不提供用于中断 copy() 或 rename() 操作的内置机制。因此,有必要考虑自定义实现策略来满足此要求。
复制中断的自定义实现
要创建非阻塞复制助手,一种选择是实现专用线程或利用主线程。无论哪种情况,都需要分段复制,即使用缓冲区以块的形式传输数据。通过使用缓冲区,可以跟踪操作进度并适应用户取消请求。
实现自定义复制助手的核心步骤可以描述如下:
使用 QMetaObject::invokeMethod() 和 Qt:: 实现一个 step() 槽QueuedConnection,允许定期处理用户事件。在此槽中:
示例实现
以下代码片段提供了复制帮助程序类的示例实现:
class CopyHelper : public QObject { Q_OBJECT Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged) public: CopyHelper(QString sPath, QString dPath, quint64 bSize = 1024 * 1024) : isCancelled(false), bufferSize(bSize), prog(0.0), source(sPath), destination(dPath), position(0) { } ~CopyHelper() { free(buff); } qreal progress() const { return prog; } void setProgress(qreal p) { if (p != prog) { prog = p; emit progressChanged(); } } public slots: void begin() { if (!source.open(QIODevice::ReadOnly)) { qDebug() << "could not open source, aborting"; emit done(); return; } fileSize = source.size(); if (!destination.open(QIODevice::WriteOnly)) { qDebug() << "could not open destination, aborting"; // maybe check for overwriting and ask to proceed emit done(); return; } if (!destination.resize(fileSize)) { qDebug() << "could not resize, aborting"; emit done(); return; } buff = (char*)malloc(bufferSize); if (!buff) { qDebug() << "could not allocate buffer, aborting"; emit done(); return; } QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection); //timer.start(); } void step() { if (!isCancelled) { if (position < fileSize) { quint64 chunk = fileSize - position; quint64 l = chunk > bufferSize ? bufferSize : chunk; source.read(buff, l); destination.write(buff, l); position += l; source.seek(position); destination.seek(position); setProgress((qreal)position / fileSize); //std::this_thread::sleep_for(std::chrono::milliseconds(100)); // for testing QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection); } else { //qDebug() << timer.elapsed(); emit done(); return; } } else { if (!destination.remove()) qDebug() << "delete failed"; emit done(); } } void cancel() { isCancelled = true; } signals: void progressChanged(); void done(); private: bool isCancelled; quint64 bufferSize; qreal prog; QFile source, destination; quint64 fileSize, position; char * buff; //QElapsedTimer timer; };
结论
通过实现自定义副本helper 或使用提供的示例,可以创建可以被用户中断的非阻塞文件复制操作。这种方法可以实现响应灵敏且用户友好的文件传输,解决因无法取消的冗长操作而造成的挫败感。
以上是如何中断 Qt 中的文件复制和重命名操作?的详细内容。更多信息请关注PHP中文网其他相关文章!