问:我如何使用QT复制大数据?

时间:2018-04-05 12:47:31

标签: c++ qt

我想读取大数据,然后使用Qt将其写入新文件。

我试过读一个大文件。大文件只有一行。我使用readAll()readLine()进行测试。

如果数据文件大约是600MB,我的代码可以运行,虽然它很慢。

如果数据文件大约为6GB,我的代码将失败。

你能给我一些建议吗?

更新
我的测试代码如下:

#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QTime>
#include <QDebug>
#define qcout qDebug()

void testFile07()
{
    QFile inFile("../03_testFile/file/bigdata03.txt");
    if (!inFile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qcout << inFile.errorString();
        return ;
    }

    QFile outFile("../bigdata-read-02.txt");
    if (!outFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
        return;

    QTime time1, time2;
    time1 = QTime::currentTime();
    while(!inFile.atEnd())
    {
        QByteArray arr = inFile.read(3*1024);
        outFile.write(arr);
    }
    time2 = QTime::currentTime();
    qcout << time1.msecsTo(time2);
}

void testFile08()
{
    QFile inFile("../03_testFile/file/bigdata03.txt");
    if (!inFile.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QFile outFile("../bigdata-readall-02.txt");
    if (!outFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
        return;

    QTime time1, time2, time3;
    time1 = QTime::currentTime();

    QByteArray arr = inFile.readAll();
    qcout << arr.size();
    time3 = QTime::currentTime();
    outFile.write(inFile.readAll());

    time2 = QTime::currentTime();
    qcout << time1.msecsTo(time2);

}

int main(int argc, char *argv[])
{
    testFile07();
    testFile08();

    return 0;
}

经过我的测试,我分享了我的经验。

  • read()readAll()似乎快速相同;实际上,read()稍快一些。
  • 真正的区别在于写作。

文件大小为600MB:
使用read功能,读取和写入 2.1s 的文件成本, 875ms 用于阅读
使用readAll功能,读取和写入 10s 的文件成本, 907ms 进行阅读

文件大小为6GB:
使用read功能,读取和写入 162s 的文件费用, 58s 用于阅读
使用readAll功能,得到错误答案0. 失败运行良好。

3 个答案:

答案 0 :(得分:7)

将这两个文件作为QFiles打开。在一个循环中,read将固定数量的字节(比如4K)从输入文件放入一个数组中,然后将write该数组放入输出文件中。继续,直到你用完字节。

但是,如果您只想逐字复制文件,可以使用QFile::copy

答案 1 :(得分:2)

您可以使用QFile::map并使用指向映射内存的指针一次性写入目标文件:

void copymappedfile(QString in_filename, QString out_filename)
{
    QFile in_file(in_filename);
    if(in_file.open(QFile::ReadOnly))
    {
        QFile out_file(out_filename);
        if(out_file.open(QFile::WriteOnly))
        {
            const qint64 filesize = in_file.size();
            uchar * mem = in_file.map(0, filesize, QFileDevice::MapPrivateOption);
            out_file.write(reinterpret_cast<const char *>(mem) , filesize);
            in_file.unmap(mem);

            out_file.close();
        }
        in_file.close();
    }
}

答案 2 :(得分:1)

要记住一件事: 使用read(),您可以为当前读取的块指定最大大小(在示例中为3 * 1024字节),使用readAll()指示程序一次读取整个文件。

在第一种情况下,您(重复地)将3072字节放在堆栈上,写入它们,一旦当前循环迭代结束,它们就会从堆栈中删除。在第二种情况下,您将整个文件推送到堆栈上。一次在堆栈上推600MB可能是您遇到性能问题的原因。如果你试图立即将6GB放在堆栈上,可能会耗尽内存/地址空间 - 导致程序崩溃。