QT在Windows中的技术总结(一):sqlite的备份还原功能(调用cmd命令模式)

由于公司在需要做QT项目,用于为产品(51单片机的)连接电脑打印串口信息。
但我以前是学嵌入式的,只会用QT在linux下面写软件,但目前公司也只有我一个软件工程师,所以,我也只好在Windows下用QT编程了。。。
网上关于QT在Windows下编程的资料很少很少,唯一我找到真正正正详细描述的昨天也已经被我转到了这里。
貌似Windows下MFC才是王道,但也真真没时间学习,此文献给所以迫不得已在Windows下使用QT的同病相怜者。
由于项目还在进行中,所以各种技术总结也在持续进行中。

首先第一篇写一下这两天纠结了很久的,QT在Windows下调用cmd命令,实现SQLite的备份还原功能。

由于犯了一个超级无敌低级错误——漏了"\n",使我失败无数次,然后也发现N种方法。

1、最简单的方法,就是调用系统命令system()函数,不用定义任何对象,直接调用,但唯一的缺点就是运行的时候,会弹出一个黑框~

例子是用最简单的复制.db文件进行备份的。

点击(此处)折叠或打开

  1. system("copy DataBase.db F:\Bak.db");


2、另外一种就是使用QProcess类,在Linux下是可以直接打命令运行的,但在Windows下貌似都没有反映,后来,先调了start个cmd出来,再write命令进去,就能运行了。

例子是调用sqlite3内部的命令

(注意必须有sqlite3.exe才能运行成功)

附上官网地址 http://www.sqlite.org/download.html  

选择 Precompiled Binaries for Windows 下的 

sqlite-shell-win32-x86-3071700.zip

点击(此处)折叠或打开

  1. QProcess *Pro;
  2. Pro = new QProcess(this);
  3. QFileDialog * file = new QFileDialog(this);
  4. QString Dir = file->getExistingDirectory(this, tr("Open Directory"),"d:\\",
  5.                                              QFileDialog::ShowDirsOnly|QFileDialog::DontResolveSymlinks);//获取文件夹路径
  6. QStringList List = Dir.split("/");
  7. Dir = List[0];
  8. for(int i=1;i<List.count();i++)
  9. {
  10.     Dir += "\\\\" + List[i];
  11. }
  12. QString Text = QString("sqlite3.exe DataBase.db \".backup \\\"%1\\\\DB_Bak.db\\\" \" \n").arg(Dir);
  13. Pro->start("Cmd");
  14. Pro->waitForStarted();
  15. Pro->write(Text.toLatin1().data());
  16. Pro->closeWriteChannel();
  17. Pro->waitForFinished();
  18. Pro->close();

需要主要的地方很多,我被卡在这里一个下午。
    首先是注意\n,另外是地址问题,明明是Windows下获取到的路径,结果地址上的连接符都是通过 / 连接的,本应该获取到的地址是D:\1\2,却变成了D:/1/2。这样的地址Windows下是不鸟你的,所以,我就通过split这个函数,先把地址用”/"截断,再用"\"组合起来,至于为什么是“\\\\"呢,这个我等下解释。虽然感觉QFileDialog是有成员函数可以将分隔号由"/"转成"\"的,但我找了半天都找不到,知道的麻烦告诉我一下吧~谢了!

   下面就来说说为什么是"\\\\"。首先看下Text这个即将传进cmd的指令。我在系统上直接运行的cmd命令是
     

  1. sqlite3.exe DataBase.db ".backup \"D:\\1\\2\\DB_Bak.db\" "

    其中\"是转义字符转成"这个不用多说了吧,同理\\也是转义字符,转成\,因为它们都在" "里面,当它们作为参数被读取的时候,都需要经过转义说明它们是字符。
    但是我们通过程序,用write()函数,把命令传进去的时候,整条命令都有" "包含,在传进去的时候就会进过一次转义,变成\\成了上面那个样子。如果只用\\,那么在传进去write的时候就会变成了\,所以在这里必须使用\\\\连续四个,才能保证经过两层转义,变成\。

    当准备好命令后,使用start()打开cmd终端,通过write()把命令写进去。这里也需要注意,write()的参数类型。


    终于成功实现功能的时候相当开心,但我发现把这条命令用在还原身上貌似不行。即使我在系统上直接运行cmd命令

  1. sqlite3.exe DB_Bak.db ".restore \"F:\\DataBase.db\""

    不仅不能实现备份还原(F:\DtatBase.db是存在的,只是里面的table都被我删了),并且DB_Bak.db里的表格都不见了!!我一直没找到原因,这个命令也是网上找到,知道原因请告诉我一下吧~
    所以用这种方式备份还原也是不可靠的,于是我又尝试了下把copy命令write到cmd中(请注意\n,system不用\n是因为它会自己加 write到cmd中,是不会自己加的)

点击(此处)折叠或打开

  1. Pro->start("Cmd");
  2. Pro->waitForStarted();
  3. Pro->write(QString("copy DataBase.db %1\\DataBase.db \n").arg(Dir).toLatin1().data());
  4. Pro->closeWriteChannel();
  5. Pro->waitForFinished();
  6. Pro->close();

    注意哦,这里不需要两次转义上面的\\\\要改回\\才行哦!
    不过这种方式也是只能备份,因为在程序中你已经在打开这个数据库(即使你已经close,你的指针已经锁定它了),不可能拿另外一个东西覆盖它(总之我的不行,你可以自己试下)。

    所以这里介绍最后一种方法,能备份也能还原其实比上面任何一种都简单= =
    这个方式在Linux下是很常用的,我以为Windows下不行的~


点击(此处)折叠或打开

  1. void Interface::Backup()//备份
  2. {
  3.     QFileDialog * file = new QFileDialog(this);
  4.     QString Dir = file->getExistingDirectory(this, tr("Open Directory"),"d:\\",
  5.                                              QFileDialog::ShowDirsOnly|QFileDialog::DontResolveSymlinks);
  6.     QStringList List = Dir.split("/");
  7.     Dir = List[0];
  8.     for(int i=1;i<List.count();i++)
  9.     {
  10.         Dir += "\\\\" + List[i];
  11.     }
  12.     QString Text = QString("sqlite3.exe DataBase.db \".dump\" > %1\\a.sql\n").arg(Dir);
  13.     Pro->start("Cmd");
  14.     Pro->waitForStarted();
  15.     Pro->write(Text.toLatin1().data());
  16.     Pro->closeWriteChannel();
  17.     Pro->waitForFinished();
  18.     Pro->close();
  19. }

 

扫描二维码关注公众号,回复: 1290138 查看本文章

点击(此处)折叠或打开

  1. void Interface::Import()//导入 
  2. {
  3.     QFileDialog * file = new QFileDialog(this);
  4.     QString Name = file->getOpenFileName(this, tr("Open DataBase"), "d:\\", tr("DataBase Files(*.sql)"));
  5.     QStringList List = Name.split("/");
  6.     Name = List[0];
  7.     for(int i=1;i<List.count();i++)
  8.     {
  9.         Name += "\\" + List[i];
  10.     }
  11.     QString Text = QString("sqlite3.exe DataBase.db < %1 \n").arg(Name);
  12.     Pro->start("Cmd");
  13.     Pro->waitForStarted();
  14.     Pro->write(Text.toLatin1().data());
  15.     Pro->closeWriteChannel();
  16.     Pro->waitForFinished();
  17.     Pro->close();
  18. }

    这方法貌似叫重定向吧,就是把数据库内容写入到文件中,还原的时候再从数据库里读出来,这方法挺好用的,程序很简单,上面的例子前面解读过了就不再累述了,导入和备份功能也差不多。

关于SQLite数据库在Windows下的使用(不使用sqlite3_exec()函数,将在下一篇中阐述。

猜你喜欢

转载自z1han.iteye.com/blog/1891058