Qt 文件处理

Qt提供了QFile类来进行文件处理,为了更方便地处理文本文件或二进制文件,Qt还提了QTextStream类和QDataStream类,处理临时文件可以使用QTemporaryFile,获取文件信息可以使用QFileInfo
,
处理目录可以使用QDir.监视文件和目录变化可以使用QFileSystemWatcher.

读写文本文件
QFile
类提供了读写文件的接口,QFile类可以读写文本文件,二进制文件和Qt资源文件,也可以使用更方便的QTextStream,QDataStream类读取文本文件和二进制文件,要打开一个文件,可以在构造函数中指定文件名,也可以在任何时候使用setFileName()函数设置文件名,打开文件使用open函数,关闭文件使用close函数。QFile中可以使用QIODevice中继承的readLine()函数读写文本文件的一行。如:
  QFile file("zeki.txt");
  if(file.open(QIODevice::ReadOnly))
  {
      char buffer[2048];
      qint 64 lineLen=file.readLine(buffer,sizeof(buffer));
      if(lineLen!=-1)
      {
         qDebug<       }
  }
如果读取成功,readLine返回实际读取的字节数,如果读取失败则返回-1
QTextStream
提供了更为方便的接口来读写文本,QTextStream可以操作QIODevice,QByteArray,QString.QTextStream使用流操作符,可以方便地读写单词,行和数字。为了产生文本,QTextStream提供了填充,对齐和数字格式化的格式选项。如
   QFile data("test.txt");
   if(data.open(QFile::WriteOnly|QFile::Truncate))
   {
        QTextStream out(&data);
        out<    }
  
QTextStream
的格式化函数
----------------------------------------------
qSetFieldWidth(int width) 
设置字段宽度
qSetPadChar(QChar ch)     
设置填充字符
qSetRealNumberPrecision(int precision)
设置实数精度
----------------------------------------------
QTextStream中使用的默认编码是QTextCodec::codecForLocal()函数返回的编码,同时能够自动检测Unicode。也可以使用QTextStream::setCodec(QTextCodec *codec)函数设置的流编码。

操作二进制文件
QDataStream
类提供了将二进制文件串行化的功能,QDataStream实现了c++基本数据类型的串行化,如char,short,int char*更复杂的数据类型串行化通过将数据类型分解为基本的数据类型来完成。下面用来写二进制数据到数据流。
QFile file("binary.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out< out<<(qint32)42<<(qint32)96;
将上面写入的文件读入的过程为:
QFile file("binary.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file);
QString str;
qint32 x,y;
in>>str>>x>>y;
每一个条目都可以定义的二进制格式写入文件,Qt中的很多类型,包括QBrush,QColor,QDateTime,QFont,QPixmap,QString,QVariant等都可以写入数据流。

如果需要读取原始数据,可以使用readRawData()读取数据到预先定义好的char *缓冲区,写原始数据使用writeData(),读写原始数据需要对数据进行编码和解码。
下面例子演示了使用QDataStream进行读写文件的过程。
#include
#include
using namespace std;
int main(int argc,char **argv)
{
   QCoreApplication app(argc,argv);
   QFile file("binary.file");
   file.open(QIODevice::WriteOnly|QIODevice::Truncate);
   QDataStream out(&file);
   out<    out<    out<<(qint32)21;
   file.close();
  
   file.setFileName("binary.file");
   if(!ifle.open(QIODevice::ReadOnly))
   {
      cout<<"
打开文件错误!";
      return 1;
   }
   QDataStream in(&file);
   QString name;
   QDate birthday;
   qint32 age;
   in>>name>>birthday>>age;
      qDebug()<       cout<       qPrintable(birthday.toString("yyyy MMMM dd dddd"));
   file.close();
   return 0;
}
在例子中,QDataStream类写入了姓名(QString),生日(QDate),和年龄(qint32)三个数据,读取时使用相同的类型读出。QDataStream可以读取任意以QIODevice为基类生成的对象产生的数据。如QTcpSocket,QUdpSocket,QBuffer,QFile,QProcess等类的数据。可以使用QDataStreamQAbstractSocket一端写入数据,另一端使用QDataStream读取数据,这样就免去了繁琐的
高低端字节转换过程。
临时文件
实际应用中有时可能需要使用临时文件,Qt中提供QTemporaryFile类来提供临时文件。QTemporayFile可以安全地创建一个第一无二的临时文件。临时文件通过open()来创建。Qt可以保证临时文件不会重复。在临时文件对象销毁后,将自动删除该临时文件。临时文件通过close()关闭后还可以打开,只要临时文件对象还没有销毁,临时文件就一直存在并由QTemporaryFile内部保持打开。系统的临时目录可以通过QDir::tempPath()来获取,unix/linux系统上的临时目录通常时/tempwindows上通常是TEM/TMP指定

 

 

2.目录操作和文件管理
QDir
类具有存取目录结构和内容的能力。使用QDir可以操作目录,存取目录或文件信息,操作底层文件系统,而且还可以存取Qt的资源文件。Qt使用/作为通用的目录分割符和URL路径分隔符。Qt可以使用相对路径和绝对路径指向一个文件,isRelative()isAbsolute()函数可以判断QDir对象使用的是相对路径还是绝对路径。将相对路径转换为绝对路径使用makeAbsolute()函数。目录路径可以通过path()函数返回,通过setPath()函数设置新路径,绝对路径使用absolutePath()返回。目录名可以使用dirName()返回。目录的路径可以通过cd() cdUp()改变,可以使用mkdir()创建目录,rename()改变目录名。判断目录是否存在可以使用exists(),目录的属性可以使用 isReadable(),isAbsolute(),isRelative()isRoot()来获取,目录下有很多条目,包括文件,目录和符号链接,总的条目数可以使用count()来统计。entryList()可以返回目录下所有条目组成的字符串链表,文件可以使用remove()函数删除,rmdir()删除目录。
linux du
命令

int main(int argc, char **argv)
{
   QCoreApplication app(argc,argv);
   QStringList args=app.arguments();
   QString path;
   if(args.count()>1)
     path=args[1];
   else
     path=QDir::currentPath();
   qDebug()<    du(path);
   return 0;
}
qint64 du(const QString &path)
{
    QDir dir(path);
    qint64 size=0;
    foreach(QFileInfo fileInfo,dir.entryInfoList(QDir::Files))
       size+=fileInfo.size();
    foreach(QString subDir,dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot))
       size+=du(path+Dir::separator()+subDir);
    char unit=\\\'B\\\';
    if(curSize>1024)
    {
       curSize/=1024;
       unit=\\\'K\\\';
       if(curSize>1024)
       {
          curSize/=1024;
          unit=\\\'M\\\';
          if(curSize>1024)
          {
            curSize/=1024;
            unit=\\\'G\\\';
          }
        }
     }
     cout<      return size;
}
函数du()中,entryInfoList(QDir::Files)函数返回文件信息,然后根据这些信息计算文件大小,接下来判断是否有子目录,如果有则递归计算。dir.etnryList(QDir::Dirs|QDir::NoDotAndDotDot)返回所有子目录并过滤掉. .. 目录。由于windows(),linux平台/ \差异,使用QDir::separator()函数来返回特定平台的目录分隔符。另外QDirIterator可以完成
枚举目录的功能,Qt4.3还引入了文件搜索前缀的概念,文件搜索前缀时至少由两个字符组成,用来搜索指定文件的路径。
QDir::setSearchPaths("docs",QStringList("c:\My Docments"));
QDir::addSearchPaht("Docs",QStringList("D:|Documents"));
QFile file("docs::qt4.doc");
这样就可以在两个目录中查找。

文件管理
QFileInfo
类提供了与系统无关的文件信心,它能提供文明名和路径,存取权限,以及文件是否为目录或符号链接,文件大小,以及最后修改/读取的时间等。QFileInfo也能从资源中获取信息。QFileInfo可以使用相对路径或绝对路径。文件名可以在QFileInfo的构造函数中传递,也可以使用setFile()函数指定,要判断一个函数是否存在,使用exits()函数,文件大小可以通过size()函数获取,文件类型可以通过isFile()isDir(),isSymLink()来获取,symLinkTarget()函数返回符号链接所指向的真正文件名。QFileInfo提供refresh函数刷新文件信息,如果需要QFileInfo每次从文件系统读取信息,二不是从缓存读取,可以使用setCaching(false)关闭缓存。文件名和目录可以通过path()fileName()分解,fileName()返回的部分可以通过baseName()extension()来获得主文件名和扩展文件名,文件的操作日期可以通过created(),lastModified()lastRead()获取,文件的存取权限可通国isReadable,isWriteable(),isExcutetable()获取,文件的属主可以通过owner(),ownerId,group(),groupId()获取,文件的权限和属主也可以通过 permission()一起读取。

监视文件系统的变化
Qt中可以使用QFileSystemWatcher类来监视文件和目录的改变.使用addPath()函数来监视指定的文件和目录,如果需要监视多个目录,使用addPaths()来加入监视,如果要一处不需要监视的目录,可以使用removePath(),removePaths()函数.当监视的文件被修改或删除时,产生一个fileChanged()信号,如果被监视的目录被修改或删除,产生directoryChanged()信号,下例实现了监视指定目录的功能.
#include
#include
#include
#Include"Msg.h"
using namespace std;
int main(int argc,char **argv)
{
    QApplication app(argc,argv);
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale())
   
    Msg msg;
    msg.show();
    return app.exec();
}
Msg::Msg()
{
   QFont font;
   font.setPointSize(24);
   setFont(font);
   QStringList args=qApp->arguments();
   QString path;
   if(args.count()>1)
     path=args[1];
   else
     path=QDir::currentPath();
   label=new QLabel();
   label->setText(tr("
监视的目录:")+path);
  
   QVBoxLayout *layout=new QVBoxLayout;
   layout->addWidget(label);
   setLayout(layout);
  
   fsWatcher.addPath(path);
   connect(&fsWatcher,SIGNAL(directoryChanged(QString)),this,SLOT(directoryChanged(QString)));
}
在构造函数中读取命令指定的目录作为监视目录,如果没有指定则监视当前目录,使用connect()函数将目录的directroyChanged()信号和响应函数连接.
void Msg::directoryChanged(QString path)
{
    QMessageBox::information(NULL,tr("
目录变化"),path);
}

文件引擎
Qt
QtDir,QFile,QFileInfo类在内部都使用一个类,QAbstractFileEngine.通过继承QAbstractFileEngine,可以编写自己的文件处理函数,然后继承QAbstractFileEngineHander类注册自己的文件引擎,然后这样就可以使用自己的文件读取引擎了.QAbstractFileEngineHandler是创建QAbstractFileEngine的类工厂.当打开一个文件时,Qt通过内部注册的文件引擎链表,选择合适的文件引擎并创建相应的引擎对象.为了安装一个特定的文件引擎,必须继承QAbstractFileEngineHandler并实现create()函数.实例化引擎时Qt自动注册该引擎,最后注册的引擎比之前注册的优先级高.
如果想读取tar文件的引擎,可以从QAbstractFileEngineHandler类继承
class TarEngineHandler:public QAbstractFileEngineHandler
{
    public:
        QAbstractFileEngine *create(const QString &fileName) const;
};
create()
函数返回TarEngine对象,TarEngine是文件引擎,时真正的文件处理类.
QAbstractFileEngine *TarEngineHandler::create(const QString &fileName) const
{
    return fileName.toLower().endsWith(".tar")?new TarEngine(fileName):0;
}

 

来源: http://blog.csdn.net/Last_Impression/archive/2008/05/08/2418878.aspx
我们使用自定义的二进制格式来实现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()清空所有的表格,因为文件中只是保存了非空的单元格数据,不能保证所有的单元格都会被设置,所以必须确保再读取单元格数据前所有的表格要清空。

你可能感兴趣的:(Qt 文件处理)