Qt4_载入和保存

这篇博客介绍了如何利用QFile和QDataStream在Qt环境中实现Spreadsheet文件的二进制读写操作。在writeFile()函数中,数据以特定格式写入文件,包括文件头和单元格数据,而readFile()函数则读取文件并验证文件格式,然后填充Spreadsheet的内容。QDataStream确保了跨平台的二进制数据兼容性,并允许设置特定的版本以兼容不同Qt版本的数据格式。
摘要由CSDN通过智能技术生成

载入和保存

现在,我们将使用一种自定义的二进制数格式来实现Spreadsheet文件的载人和保存。将使用QFile和QDataSrean来完成这一工作,由它们共同提供与平台无关的二进制数输入/输出接口。

首先从一个Spreadsheet文件的输出开始:

bool Spreadsheet::writeFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly)) {
        QMessageBox::warning(this, tr("Spreadsheet"),
                             tr("Cannot write file %1:\n%2.")
                             .arg(file.fileName())
                             .arg(file.errorString()));
        return false;
    }

    QDataStream out(&file);
    out.setVersion(QDataStream::Qt_4_3); //Qt_4_3 = 9

    out << quint32(MagicNumber);

    QApplication::setOverrideCursor(Qt::WaitCursor);
    for (int row = 0; row < RowCount; ++row) {
        for (int column = 0; column < ColumnCount; ++column) {
            QString str = formula(row, column);
            if (!str.isEmpty())
                out << quint16(row) << quint16(column) << str;
        }
    }
    QApplication::restoreOverrideCursor();
    return true;
}

从MainWindow::saveFile()中调用的writeFile()函数把文件输出到磁盘中。如果输出成功,它会返回true;如果出现错误,则返回false。

我们使用给定的文件名创建一个QFile对象,并且调用open()打开这个用于输出的文件。我们也会创建一个QDataStream对象,由它操作这个QFile对象并且使用该对象输出数据。

在输出数据之前,我们把这个应用程序的光标修改为标准的等待光标(通常是一个沙漏),并且一旦所有的数据输出完毕,就需要把这个应用程序的光标重新恢复为普通光标。在函数的最后,文件会由QFile对象的析构函数自动关闭。

QDataStream 支持基本的 C++类型,也支持多种 Qt 类型。语法和标准 C++<iostream>
类是一样的。例如:

out << x << y << z;

把变量 x,y,z 写入数据流。

in >> x >> y >> z;

会从流中读出它们。

在不同的平台上,基本的 C++类型如short,char,int,long,long long 会有不同的字长,所以把它们强制转换为 qint8,quint8,qint16,quint16,qint32,quint32,qint64,quint64,这些类型能确保字长是不随平台改变的。

Spreadsheet应用程序的文件格式是相当简单的。一个Spreadsheet文件以一个32位数字作为文件的开始,由它确定文件的格式(MagicNumber,在sreadsheet.h中定义为0x7F51C883,它是一个任意的随机数)。然后是连续的数据块,每一数据块都包含了用于一个单元格中的行、列和公式。为了节省空间,我们没有输出空白单元格。
在这里插入图片描述
关于这些数据类型的二进制数确切表示方法则是由QDataStream决定的。例如,一个quint16按照高字节在后的顺序存储为两个字节,而一个QString则被存储为字符串的长度后跟Unicode字符的形式。

关于Qt数据类型的二进制数确切表示方法,自Qt 1.0以来已经发生了许多变化。而且在未来的Qt发行版中,为了能够与现存的数据类型和将来允许出现的新的Qt类型保持一致,这样的表示方法还可能会继续变化下去。默认情况下,QDataSrean会使用最近版本的二进制数格式(在Qt 4.3中的版本是第9版) ,但是可以设置它,使它可以读取那些旧的数据版本。如果以后有可能使用新的Qt发行版来重新编译这个应用程序,那么为了避免出现任何可能的兼容性问题,需要明确告诉QDataSream应该使用的是第9版,从而无需再考虑要使用的Qt版本。(QDataStream::Qt_4_3是一
个方便的常量,它就等于9。)

QDataStream 可以支持多种类型。如 QFile,QBuffer,QProcess,QTcpSocket 或者QUdpSocket。Qt 还提供了类 QTextStream 能够读写文本文件。

bool Spreadsheet::readFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(this, tr("Spreadsheet"),
                             tr("Cannot read file %1:\n%2.")
                             .arg(file.fileName())
                             .arg(file.errorString()));
        return false;
    }

    QDataStream in(&file);
    in.setVersion(QDataStream::Qt_4_3);

    quint32 magic; //用于匹配文件格式
    in >> magic;
    if (magic != MagicNumber) {
        QMessageBox::warning(this, tr("Spreadsheet"),
                             tr("The file is not a Spreadsheet file."));
        return false;
    }

    clear();

    quint16 row;
    quint16 column;
    QString str;

    QApplication::setOverrideCursor(Qt::WaitCursor);
    while (!in.atEnd()) {
        in >> row >> column >> str;
        setFormula(row, column, str);
    }
    QApplication::restoreOverrideCursor();
    return true;
}

readFile()函数与writeFile() 函数非常相似。我们使用QFile读取一个文件,但这一次使用的是QIODevice::ReadOnly标记,而不是QIODevice::WriteOnly标记。然后,把QDataStream的版本设置为9。用于读取文件的格式必须总是与输出文件的格式相同。

如果该文件在开始处具有正确的幻数(magic number),那么可以调用clear()来清空电子制表软件中的所有单元格,并且读入单元格中的数据。由于该文件中只包含那些非空单元格的数据,并且也不大可能重置电子制表软件中的每个单元格,所以必须确保在读入数据之前已经清空了所有的单元格。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值