进度条带有QFile::copy()
Progress bar with QFile::copy()?
我正在制作一个在Qt中复制文件的程序,我想知道如何使用QProgressBar
和bool QFile::copy(const QString & fileName, const QString & newName)
。这是可能的copy
函数吗?复制过程可以暂停吗?
不能使用静态QFile::copy()方法。
正如Maciej之前所说,您需要编写自己的类。它应该使用两个QFile对象,一个用于读,一个用于写。按部分传输数据(例如,整个文件大小的1%),并在每个部分之后发出进度信号。您可以将此信号连接到进度对话框。
如果你需要它在后台工作,你应该使用QThread来实现它。
首先尝试决定是否需要一个类来异步地(不阻塞GUI)或同步地(阻塞GUI)执行复制工作。后者更容易编程,但大多数时候不是你想要的(例如,如果GUI被阻塞,你不能通过点击按钮来取消或暂停复制操作)。
您可以在这里查看一个相当广泛的Qt 4类:http://docs.huihoo.com/qt/solutions/4/qtcopydialog/qtfilecopier.html但我不确定这是否会有所帮助,因为它的复杂性。
这是一个最小的示例:
filecopyer.h
:
/*
* This is a minimal example to show thread-based QFile copy operation with progress notfication.
* See here for QFile limitations: https://doc.qt.io/qt-5/qfile.html#platform-specific-issues
* Copyright (C) 2019 Iman Ahmadvand
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _FILE_COPYER_H
#define _FILE_COPYER_H
#include <QtCore/qstring.h>
#include <QtCore/qobject.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qvector.h>
#include <QtCore/qthread.h>
class FileCopyer : public QObject {
Q_OBJECT
Q_PROPERTY(qint64 chunksize READ chunkSize WRITE setChunkSize)
Q_PROPERTY(QVector<QString> sourcePaths READ sourcePaths WRITE setSourcePaths)
Q_PROPERTY(QVector<QString> destinationPaths READ destinationPaths WRITE setDestinationPaths)
public:
static const int DEFAULT_CHUNK_SIZE = 1024 * 1024 * 1;
FileCopyer(QThread*);
~FileCopyer();
qint64 chunkSize() const {
return _chunk;
}
void setChunkSize(qint64 ch) {
_chunk = ch;
}
QVector<QString> sourcePaths() const {
return src;
}
void setSourcePaths(const QVector<QString>& _src) {
src = _src;
}
QVector<QString> destinationPaths() const {
return dst;
}
void setDestinationPaths(const QVector<QString>& _dst) {
dst = _dst;
}
protected slots:
void copy();
private:
QVector<QString> src, dst;
qint64 _chunk;
signals:
void copyProgress(qint64 bytesCopied, qint64 bytesTotal);
void finished(bool success);
};
#endif // !_FILE_COPYER_H
filecopyer.cpp
:
/*
* This is a minimal example to show thread-based QFile copy operation with progress notfication.
* See here for QFile limitations: https://doc.qt.io/qt-5/qfile.html#platform-specific-issues
* Copyright (C) 2019 Iman Ahmadvand
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <QtCore/qdebug.h>
#include "filecopyer.h"
FileCopyer::FileCopyer(QThread* _thread) :QObject(nullptr) {
moveToThread(_thread);
setChunkSize(DEFAULT_CHUNK_SIZE);
QObject::connect(_thread, &QThread::started, this, &FileCopyer::copy);
QObject::connect(this, &FileCopyer::finished, _thread, &QThread::quit);
QObject::connect(this, &FileCopyer::finished, this, &FileCopyer::deleteLater);
QObject::connect(_thread, &QThread::finished, _thread, &QThread::deleteLater);
}
FileCopyer::~FileCopyer() {
}
void FileCopyer::copy() {
if (src.isEmpty() || dst.isEmpty()) {
qWarning() << QStringLiteral("source or destination paths are empty!");
emit finished(false);
return;
}
if (src.count() != dst.count()) {
qWarning() << QStringLiteral("source or destination paths doesn't match!");
emit finished(false);
return;
}
qint64 total = 0, written = 0;
for (const auto& f : src)
total += QFileInfo(f).size();
qInfo() << QStringLiteral("%1 bytes should be write in total").arg(total);
int indx = 0;
qInfo() << QStringLiteral("writing with chunk size of %1 byte").arg(chunkSize());
while (indx < src.count()) {
const auto dstPath = dst.at(indx);
QFile srcFile(src.at(indx));
QFile dstFile(dstPath);
if (QFile::exists(dstPath)) {
qInfo() << QStringLiteral("file %1 alreasy exists, overwriting...").arg(dstPath);
QFile::remove(dstPath);
}
if (!srcFile.open(QFileDevice::ReadOnly)) {
qWarning() << QStringLiteral("failed to open %1 (error:%1)").arg(srcFile.errorString());
indx++;
continue; // skip
}
if (!dstFile.open(QFileDevice::WriteOnly)) {
qWarning() << QStringLiteral("failed to open %1 (error:%1)").arg(dstFile.errorString());
indx++;
continue; // skip
}
/* copy the content in portion of chunk size */
qint64 fSize = srcFile.size();
while (fSize) {
const auto data = srcFile.read(chunkSize());
const auto _written = dstFile.write(data);
if (data.size() == _written) {
written += _written;
fSize -= data.size();
emit copyProgress(written, total);
} else {
qWarning() << QStringLiteral("failed to write to %1 (error:%2)").arg(dstFile.fileName()).arg(dstFile.errorString());
fSize = 0;
break; // skip this operation
}
}
srcFile.close();
dstFile.close();
indx++;
}
if (total == written) {
qInfo() << QStringLiteral("progress finished, %1 bytes of %2 has been written").arg(written).arg(total);
emit finished(true);
} else {
emit finished(false);
}
}
main.cpp
:
#include <QtWidgets/QApplication>
#include "filecopyer.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
auto local = new QThread;
auto worker = new FileCopyer(local);
QObject::connect(worker, &FileCopyer::finished, [](bool s) {
s ? qDebug() << "FINISHED" : qDebug() << "FAILED";
});
QObject::connect(worker, &FileCopyer::copyProgress, [](qint64 copy, qint64 total) {
qDebug() << QStringLiteral("PROGRESS => %1").arg(qreal(copy) / qreal(total) * 100.0);
});
worker->setSourcePaths(/* src-paths */); // e.g: ~/content/example.mp4
worker->setDestinationPaths(/* dst-paths */); // e.g /usr/local/example.mp4
local->start();
return a.exec();
}
检查QFile
从QIODevice派生的类,有一个信号bytesWritten()
连接到它并通过QFileInfo(fromFile).size()
启动文件大小以获得读取如何使用信号检查我的其他答案
相关文章:
- std::filesystem::copy throws filesystem_error
- 如何在 Boost.Asio 中使用 Zero-copy sendmsg/receive
- 如何从QFile阅读?它显示该文件不可访问
- QDial:如何将 int 值传递给需要常量字符*的 Qfile?
- QDataStream 读取和写入的字节数比 QFile::length() 报告要多
- Qt 写入 xml: QIODevice::write (QFile, "D:/logs.xml" ): 设备未打开
- C++ 一个lambda浅拷贝const Type&如果它被赋予一个命名捕获,如[copy=val](){}?
- QML/C++/QObject Struct Copy
- C++赋值运算符,我们可以用 copy 替换它吗?
- 为什么我使用 std::copy() 收到运行时错误(分段错误)?
- 如何解决C++中声纳库贝静态代码分析错误"Explicitly define the missing copy constructor, move constructor .."
- 如何使用 std::copy 当类有"无符号字符和运算符[]"时
- std::copy 导致运行时检查失败 #2
- 为什么 Clang 在命名空间'std'中没有名为 'copy' 的成员给出错误
- Qt中的QFile::copy(source,dest)的实现有时是错误的吗?
- QFile copy - 静态对象与临时对象
- 将 QFile::copy 创建创建文件的副本或将内容从一个文件移动到另一个文件
- return QFile::copy from web
- QFile::copy异常行为
- 进度条带有QFile::copy()