(转)4.3加载和保存(Loading and Saving)

xiaoxiao2021-02-28  109

我们使用自定义的二进制格式来实现Spreadsheet文件的保存和读取。我们用QFile和QDataStream这两个类来实现,它们一起提供了平台无关的二进制I/O。 首先是保存文件的代码: bool  Spreadsheet::writeFile( const  QString  & fileName) {     QFile file(fileName);      if  ( ! file.open(QIODevice::WriteOnly)) {         QMessageBox::warning( this , tr( " Spreadsheet " ),                              tr( " Cannot write file %1: %2. " )                              .arg(file.fileName())                              .arg(file.errorString()));          return   false ;     }     QDataStream  out ( & file);      out .setVersion(QDataStream::Qt_4_1);      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 ; } 函数writeFile()由MainWindow::saveFile()调用,把文件保存到磁盘上。如果保存成功返回true,否则返回false。 首先我们使用给定的程序名创建一个QFile对象,调open()打开这个文件准备写入。同时创建一个QDataSteam对象来操作QFile对象,将数据写入文件中。 在写数据之前,我们将程序的光标换成等待形式,数据写完后恢复原来的鼠标形状。函数结束时,QFile的析构函数把文件自动关闭。 QDataStream支持基本的C++类型,也支持多种Qt类型。语法和标准C++<iostream>类是一样的。例如: Out<<x<<y<<z;把变量x,y,z写入数据流。 In>>x>>y>>z; 从数据流中读取数据到x,y,z中。在不同的平台上,基本的C++类型如short,char,int,long,long long会有不同的字长。最好把它们转换为qint8,quint8,qint16,quint16,qint32,quint32,qint64,quint64,这些类型能确保字长是不随平台改变的。 Spreadsheet程序的文件格式非常简单。一个Spreadsheet文件开头部分是一个32位的标识数字(MagciNumber,在spreadsheet.h中定义的,一个二进制的随机数),这个数字后面是一系列的数据块,包括一个单元格的行号,列号和公式组成。为了节省空间,不保存空的单元格。 数据类型的二进制表示由类QDataStream决定。如:quint16表示按big-endian顺序保存为两个字节。一个QString类型表示是字符串的长度后面接着Unicode码组成。 自Qt1.0以来,Qt数据类型的二进制表示有了很大变化。在未来的Qt版本中还可能有更多的改变,默认QDataStream使用最近的Qt版本的二进制格式(version 7 in Qt 4.1),但是它可以读取以前的版本。为了程序用新的Qt版本重新编译后能够更好的兼容,我们显式的给出QDataStream使用的版本为7(QDataStream::Qt_4_1定义为常量7) QDataStream可以支持多种类型。如QFile,QBuffer,QProcess,QTcpSocket或者QUdpSocket。Qt还提供了类QTextStream能够读写文本文件。第12章详细介绍这些类。 读取文件如下: bool  Spreadsheet::readFile( const  QString  & fileName) {     QFile file(fileName);      if  ( ! file.open(QIODevice::ReadOnly)) {         QMessageBox::warning( this , tr( " Spreadsheet " ),                              tr( " Cannot read file %1: %2. " )                              .arg(file.fileName())                              .arg(file.errorString()));          return   false ;     }     QDataStream  in ( & file);      in .setVersion(QDataStream::Qt_4_1);     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()很相似。这次文件的打开方式为QIODevice::ReadOnly而不是QIODevice::writeOnly。设置QDataStream的版本为7。写文件和读文件的版本必须一致。 如果文件的magic number号是正确的,调用clear()清空所有的表格,因为文件中只是保存了非空的单元格数据,不能保证所有的单元格都会被设置,所以必须确保再读取单元格数据前所有的表格要清空。
转载请注明原文地址: https://www.6miu.com/read-26519.html

最新回复(0)