qfile将文件保存在程序QUIT上,根本不会保存〜500MB的文件
-
20-12-2019 - |
题
是的,这是我的再次。我有以下代码:
void MainWindow::on_startButton_clicked()
{
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
QNetworkReply *re = nam->get(QNetworkRequest(QUrl("http://somesite/ai/iai.jpg")));
QEventLoop loop;
QObject::connect(reply, SIGNAL(readyRead()), &loop, SLOT(quit()));
loop.exec();
ui->dbgOut->insertHtml("<font color='green'>OK</font><br>");
ui->dbgOut->insertHtml("##################################");
//save
QFile file("C:\\a.bin");
file.open(QIODevice::WriteOnly);
file.write(re->readAll());
file.close();
}
.
,我有两个问题:
-
当我点击按钮时,它下载文件但不会将它们写入HDD。我可以等待5,10分钟,什么都没有。此时,整个文件存储在程序内存中。如果我关闭了我的程序,它们会保存在磁盘上。
-
大文件(〜500mb)根本没有保存。当我关闭程序时,它立即崩溃。
我如何编辑它,以便我的程序将保存下载的文件“实时”?
解决方案
非交互性是因为具有未知大小的设备上的生成播放代码是阻塞呼叫。它将继续阅读,直到请求完成。
大文件的问题与veryte数组一起携带,该问题与包含该文件的字节数组有关。在某些时候,你的字节数组将是,说400MB,然后它必须成长为2倍的大小,所以你必须在两个大块的两个大块中保持〜1GB,并且由于地址空间碎片分配请求将失败,您的程序崩溃。
对代码的严格更改产生所需的行为:您立即开始阅读和写作,只需链接两者:
class MainWindow {
...
// You shouldn't be creating a new network access manager for each request.
QScopedPointer<QNetworkAccessManager> m_nam;
...
};
void MainWindow::handleError(const QNetworkReply *) { ... }
void MainWindow::handleError(const QFile *) { ... }
void MainWindow::on_startButton_clicked()
{
// Lazily create the network access manager once.
if (!m_nam) m_nam.reset(new QNetworkAccessManager);
// The file is destructed, and thus flushed and closed, when the
// last shared pointer to this file is destructed.
QSharedPointer<QFile> output(new QFile("C:\\a.bin"));
if (!output->open(QIODevice::WriteOnly)) return;
QNetworkReply *reply = m_nam->get(QNetworkRequest(QUrl("http://somesite/ai/iai.jpg")));
// The lambda syntax creates a functor object that holds a copy
// of the reply pointer and the output file pointer.
// This functor will be destructed when the reply is destructed.
QObject::connect(reply, &QIODevice::readyRead, [this, output, reply]{
QByteArray data(reply->bytesAvailable(), Qt::Uninitialized);
qint64 in = reply->read(data.data(), data.size());
qint64 out = output->write(in);
if (in < 0) {
handleError(reply);
reply->deleteLater();
}
else if (out != in) {
handleError(output.data());
reply->deleteLater();
}
});
// The reply will self-destruct when finished, thus deleting the file
// instance.
QObject::connect(reply, &QNetworkReply::finished, reply, &QObject::deleteLater);
}
. 不隶属于 StackOverflow