文章目录
4.3 载入和保存
现在,我们将使用一种自定义的二进制数格式来实现Spreadsheet文件的载人和保存。将使用QFile和QDataSrean来完成这一工作,由它们共同提供与平台无关的二进制数输入/输出接口。
bool Spreadsheet::writeFile(const QString &fileName)
{
/* 从MainWindow::saveFile()中调用的writeFile()函数把文件输出到磁盘中。
* 如果输出成功,它会返回true;如果出现错误,则返回false。
* 我们使用给定的文件名创建一个QFile对象,并且调用open()打开这个用于输出的文件。
* 我们也会创建一个QDataStream对象,由它操作这个QFile对象并且使用该对象输出数据。
* 在输出数据之前,我们把这个应用程序的光标修改为标准的等待光标(通常是一个沙漏),并且一旦所有的数据输出完毕,就需要把这个应用程序的光标重新恢复为普通光标。
* 在函数的最后,文件会由QFile对象的析构函数自动关闭。
*/
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;
}
Spreadsheet应用程序的文件格式是相当简单的。一个Spreadsheet文件以一个32位数字作为文件的开始,由它确定文件的格式(MagicNumber,在sreadsheet.h’中定义为0x7F51C883,它是一个任意的随机数)。然后是连续的数据块,每一数据块都包含 了用于一个单元格中的行、列和公式。为了节省空间,我们没有输出空白单元格。该文件格式如图4.3所示。
关于这些数据类型的二进制数确切表示方法则是由QDataStream决定的。例如,一个quint16按照高字节在后的顺序存储为两个字节,而一个QString则被存储为字符串的长度后跟Unicode字符的形式。
关于Qt数据类型的二进制数确切表示方法,自Qt 1.0以来已经发生了许多变化。而且在未来的Qt发行版中,为了能够与现存的数据类型和将来允许出现的新的Qt类型保持一致, 这样的表示方法还可能会继续变化下去。默认情况下,QDataSrean会使用最近版本的二进制数格式(在Qt 4.3中的版本是第9版) ,但是可以设置它,使它可以读取那些旧的数据版本。如果以后有可能使用新的Qt发行版来重新编译这个应用程序,那么为了避免出现任何可能的兼容性问题,需要明确告诉QDataSream应该使用的是第9版,从而无需再考虑要使用的Qt版本。(QDataStream::Qt_4_3是一
个方便的常量,它就等于9。)
bool Spreadsheet::readFile(const QString &fileName)
{
/* readFile()函数与writeFile() 函数非常相似。
* 我们使用QFile读取一个文件,但这一次使用的是QIODevice::ReadOnly标记,而不是QIODevice::WriteOnly标记。
* 然后,把QDataStream的版本设置为9。
* 用于读取文件的格式必须总是与输出文件的格式相同。