设为首页 收藏本站
查看: 2100|回复: 0

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

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

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

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

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

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


  点击(此处)折叠或打开


  • 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


  点击(此处)折叠或打开


  • QProcess *Pro;

  • Pro = new QProcess(this);
  • QFileDialog * file = new QFileDialog(this);
  • QString Dir = file->getExistingDirectory(this, tr("Open Directory"),"d:\\",
  •                                              QFileDialog::ShowDirsOnly|QFileDialog::DontResolveSymlinks);//获取文件夹路径
  • QStringList List = Dir.split("/");
  • Dir = List[0];
  • for(int i=1;i<List.count();i++)
  • {
  •     Dir += "\\\\" + List[i];
  • }
  • QString Text = QString("sqlite3.exe DataBase.db \".backup \\\"%1\\\\DB_Bak.db\\\" \" \n").arg(Dir);

  • Pro->start("Cmd");
  • Pro->waitForStarted();
  • Pro->write(Text.toLatin1().data());
  • Pro->closeWriteChannel();
  • Pro->waitForFinished();
  • Pro->close();


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

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


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

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

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


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



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

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


  点击(此处)折叠或打开


  • Pro->start("Cmd");

  • Pro->waitForStarted();
  • Pro->write(QString("copy DataBase.db %1\\DataBase.db \n").arg(Dir).toLatin1().data());
  • Pro->closeWriteChannel();
  • Pro->waitForFinished();
  • Pro->close();


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

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



  点击(此处)折叠或打开


  • void Interface::Backup()//备份

  • {
  •     QFileDialog * file = new QFileDialog(this);
  •     QString Dir = file->getExistingDirectory(this, tr("Open Directory"),"d:\\",
  •                                              QFileDialog::ShowDirsOnly|QFileDialog::DontResolveSymlinks);
  •     QStringList List = Dir.split("/");
  •     Dir = List[0];
  •     for(int i=1;i<List.count();i++)
  •     {
  •         Dir += "\\\\" + List[i];
  •     }
  •     QString Text = QString("sqlite3.exe DataBase.db \".dump\" > %1\\a.sql\n").arg(Dir);
  •     Pro->start("Cmd");
  •     Pro->waitForStarted();
  •     Pro->write(Text.toLatin1().data());
  •     Pro->closeWriteChannel();
  •     Pro->waitForFinished();
  •     Pro->close();
  • }


   
  点击(此处)折叠或打开


  • void Interface::Import()//导入 

  • {
  •     QFileDialog * file = new QFileDialog(this);
  •     QString Name = file->getOpenFileName(this, tr("Open DataBase"), "d:\\", tr("DataBase Files(*.sql)"));
  •     QStringList List = Name.split("/");
  •     Name = List[0];
  •     for(int i=1;i<List.count();i++)
  •     {
  •         Name += "\\" + List[i];
  •     }
  •     QString Text = QString("sqlite3.exe DataBase.db < %1 \n").arg(Name);
  •     Pro->start("Cmd");
  •     Pro->waitForStarted();
  •     Pro->write(Text.toLatin1().data());
  •     Pro->closeWriteChannel();
  •     Pro->waitForFinished();
  •     Pro->close();

  • }


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

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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-308225-1-1.html 上篇帖子: 无废话Android 系列教程35 [Android下的数据库SQLite事务概念及使用&&测试] 下篇帖子: Android中结合OrmLite for android组件对SQLite的CRUD(增删改查)操作实例
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表