在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在QT中通过QProcess类调用命令行的rar.exe来达到效果,但是没想到QProcess类用起来很麻烦,而且达不到效果,折腾了2天仍然没找到原因,使用另外一种办法解决了。

创建压缩包的方法

在windows平台创建压缩包,可以直接使用rar.exe,该程序在安装winrar之后,在其安装目录下就可以找到。该程序是winrar对应的命令行版本,其语法例子如下:

rar.exe a -k -r -s -m1 test.rar direct1/   direct2/  test.txt

例子对应的目录结构如下:

上面的命令表示在当前目录下创建压缩包 test.rar ,将当前目录下的 direct1目录以及其所有子目录和文件、direct2目录以及其子目录和文件、当前目录下的文件test.txt 都添加到test.rar压缩包中。

其中参数a表示添加到压缩包

参数-r表示递归添加

命令的问题解决了之后,那么下面就是如何在QT中调用该命令,实际上在QT中调用该命令就出现了很多问题。

在QT中调用命令行

QT中调用外部命令一般使用QProcess类提供的成员函数,其使用的具体代码如下:

QProcess p(0);
p.start(command,args); //command是要执行的命令,args是参数
p.waitForFinished();//等待完成
qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());

套用上面的代码得到如下:

QProcess p(0);
QString command = "E:/test_rar_course/rar.exe";
QStringList args;
args.append("a");
args.append("-k");
args.append("-r");
args.append("-s");
args.append("-m1");
args.append("E:/test_rar_course/test.rar");
args.append("E:/test_rar_course/direct1/");
args.append("E:/test_rar_course/direct2/");
args.append("E:/test_rar_course/test.txt");
p.execute(command,args);//command是要执行的命令,args是参数
p.waitForFinished();
qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());

可以生成test.rar但是,该压缩包中将路径E:/test_rar_course也压缩进去了,而我需要的是打开压缩包之后仅仅看到direct1,direct2,test.txt3个项目,那么是不是设置一下工作目录就可以了呢:

QProcess p(0);
p.setWorkingDirectory("E:/test_rar_course/");//指定进程的工作目录
QString command = "E:/test_rar_course/rar.exe";
QStringList args;
args.append("a");
args.append("-k");
args.append("-r");
args.append("-s");
args.append("-m1");
args.append("-wE:/test_rar_course/");//指定rar.exe的工作目录
args.append("test.rar");
args.append("direct1/");
args.append("direct2/");
args.append("test.txt");
p.execute(command,args);//command是要执行的命令,args是参数
p.waitForFinished();
qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());//获取输出

我不仅添加-w参数(该参数为rar.exe的命令行参数,用于指定工作目录)为rar.exe命令指定工作目录,同时利用p.setWorkingDirectory()为启动的进程指定工作目录,运行之后报错,说找不到文件,我猜可能还是工作目录的问题,但是不知道问题在哪里,查了很多资料都无济于事,最终还是放弃了这种尝试,改成了下面的尝试:

QProcess p(0);
p.setWorkingDirectory("E:/test_rar_course/");//指定进程的工作目录
QString command = "E:/test_rar_course/test.bat";
p.start(command);
p.waitForFinished();
qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());

而test.bat的内容为如下:

cd /d E:/test_rar_course/
E:/test_rar_course/rar.exe a -k -r -s -m1 -wE:/test_rar_course/ test.rar direct1/ direct2/ test.txt

我直接在bat中通过cd命令切换工作目录,然后进行压缩,其中为了避免出现压缩绝对路径的情况,direct1,direct2,test.txt使用的都是相对路径,直接鼠标双击该test.bat运行OK,放在QT中运行OK,似乎完美的解决了问题。

但是我发现,如果目录中出现()括号字符就不行了,当有括号字符的时候在QProcess执行的报错中显示路径被括号截断,此后我把路径用引号引起来没效果:

"\"E:/test_rar_course(xx)/test.bat\""

根据网上搜索到的信息,用^符号对括号进行转义没有截断的报错了,但是命令执行还是没有效果,控制台也没有报错:

"E:/test_rar_course^(xx^)/test.bat"

到这里我不知道该怎么样去达到我的效果,唯一的感觉QProcess怎么这么难用,如果有知道的QT大神,烦请告诉一下。我想到用另外一种方式来实现,就是用C++写一个dll实现,然后QT中调用。

在QT中调用C++创建的dll

主要代码如下,实际上就是调用system函数,但是如果路径中有圆括号,还是需要用^符号进行转义,否则system执行也有问题:

void SystemTool::GenerateIndexRar(char * command)
{
if(command == NULL) return ;
system(command);
}

但是除了圆括号要转义以外,还存在一个很不舒服的问题,就是每次执行都会弹出cmd的黑窗口,执行完成之后,窗口消失,代码改成下面的就好了:

#include <windows.h>
void SystemTool::GenerateIndexRar(char * command)
{
if(command == NULL) return ;
/**
WinExec 的windows 调用,可以通过参数SW_HIDE隐藏命令行黑窗口
并且命令的路径是可以带括号的
*/
WinExec(command,SW_HIDE);
}

到此完美解决该问题,既不需要对圆括号进行转义,同时也隐藏了黑窗口了。当然前述的test.bat的内容要在程序中动态生成,利用合适的路径替换掉test.bat中的路径。

最后调用如:SystemTool::GenerateIndexRar("E:/test_rar_course(xx)/test.bat");

QT中QProcess调用命令行的痛苦经历的更多相关文章

  1. QT中QProcess调用命令行的痛苦经历(调用Winrar,设置工作目录,获得输出,注意引号与括号,等等)

    QT中QProcess调用命令行的痛苦经历   阅读目录 创建压缩包的方法 在QT中调用命令行 在QT中调用C++创建的dll 在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在Q ...

  2. C 语言中可以调用命令行指令的 system()函数

    C语言有一个system函数(在<stdlib.h>头中,C++则为<cstdlib>头),可以用来调用终端命令.原型如下: int system(const char *cm ...

  3. Qt_Window@Qt Command Prompt从命令行创建工程

    #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplicatio ...

  4. npm中本地安装命令行类型的模块是不注册Path的

    http://www.jianshu.com/p/c04dea6e46de 首先有必要解释下什么是命令行(Command Line)类型的模块.npm的模块一共分为三类: 绑定型(Binding):本 ...

  5. 通过JAVA调用命令行程序

    这是我在把数据导入到数据库时遇到问题,总结下来的.包含两个方法,一个方法是读取文件路径下的文件列表,主方法是执行cmd命令,在导入时想得到导入一个文件的时间,涉及到线程阻塞问题,这个问题理解不是很深, ...

  6. system调用命令行命令而不显示命令行窗口

    system调用命令行命令而不显示命令行窗口 通常用system调用命令行命令时都会弹出黑底白字的命令行窗口,下面的代码可以不显示弹出的命令行窗口. 代码如下 #pragma comment( lin ...

  7. Vim中常用的命令行

    Vim中常用的命令行... ------------------- 一些真正强大的武器总不是那么容易驾驭的,主角总得付出一些努力才能收获到更加强大的力量,对于 Vim 这种上古神器来说更是如此.由于它 ...

  8. QT uic rcc moc 命令行使用

    QT uic rcc moc 命令行使用 PS C:\Users\lsgx> uic.exe --help Usage: C:\Qt\Qt5.5.1\5.5\msvc2012\bin\uic.e ...

  9. Ruby(或cmd中)输入命令行编译sass

    Ruby(或cmd中)输入命令行编译sass步骤如下: 举例: 1.在F盘中新建一个总文件夹,比如test文件夹,其中在该文件夹下面建立html.images.js.sass等文件夹. 2.在sass ...

随机推荐

  1. 使用percona-xtrabackup实现对线上zabbix监控系统数据库mariadb5.5.47的主从同步

    使用percona-xtrabackup实现对线上zabbix监控系统数据库的主从同步 业务背景: zabbix3.0.4是业务的主要监控,部署在一台单机中,为避免数据丢失先对其做数据主从同步,因主数 ...

  2. linux vim 替换指定字符为回车

    有个问题,想要知道逗号分隔的字符串  example: aaa,bbb,ccc 分隔后的个数 1 将   aaa,bbb,ccc 替换成 aaa bbb ccc 方法: :%s/,/^M/g ^M是用 ...

  3. jstl <c:forEach> 介绍

    varStatus是<c:forEach>jstl循环标签的一个属性,varStatus属性.就拿varStatus="status"来说,事实上定义了一个status ...

  4. 开发BBS论坛

    一.涉及表结构 web\model.py(首选需要注意表结构的设计,如果表结构设计出来了,软件的架构也就基本出来了) #!/usr/bin/env python # _*_ coding:utf- _ ...

  5. 关于Eclipse项目中加入jquery.js文件报错(missing semicolon)问题

    在使用Eclipse3.7及以后的版本的时候,加入jQuery文件会报错(missing semicolon),文件中会显示红色小X,虽然这个错误并不会影响项目的运行,但是这个却会大大的影响到开发人员 ...

  6. php 文件读取

    整理了一下PHP中读取文件的几个方法,方便以后查阅. 1.fread string fread ( int $handle , int $length ) fread() 从 handle 指向的文件 ...

  7. iOS崩溃日志记录工具--CrashlyTics

    http://try.crashlytics.com Crashlytics优势: 1.Crashlytics基本不会漏掉任何应用崩溃的信息 2.Crashlytics对崩溃日志管理很人性化,会根据崩 ...

  8. ca des key crt scr

    openssl genrsa -des3 -out domain.key 1024 openssl req -new -key domain.key -out domain.csr openssl r ...

  9. Hosting static website on AWS

    http://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html#root-d ...

  10. 【转载】Windows自带.NET Framework版本大全

    转载自:http://blogs.msdn.com/b/astebner/archive/2007/03/14/mailbag-what-version-of-the-net-framework-is ...