Qt君今天看到QProcess源码中发现两个start函数行为不一样。顺便解决了对于传入的命令带有空格不能正常执行的问题。
start函数1
void QProcess::start(const QString &command, OpenMode mode)
{
/* 会对传入的命令(command)分解。 */
QStringList args = parseCombinedArgString(command);
...
start(prog, args, mode);
}
/* 如果字符串没有以连续三个"分隔,则判定以空格分隔参数。 */
static QStringList parseCombinedArgString(const QString &program)
{
...
// handle quoting. tokens can be surrounded by double quotes
// "hello world". three consecutive double quotes represent
// the quote character itself.
for (int i = 0; i
if (program.at(i) == QLatin1Char('"')) {
++quoteCount;
if (quoteCount == 3) {
// third consecutive quote
quoteCount = 0;
tmp += program.at(i);
}
continue;
}
if (quoteCount) {
if (quoteCount == 1)
inQuote = !inQuote;
quoteCount = 0;
}
if (!inQuote && program.at(i).isSpace()) {
if (!tmp.isEmpty()) {
args += tmp;
tmp.clear();
}
} else {
tmp += program.at(i);
}
}
...
}
简单使用小例子:
QProcess process;
/* 这种方法如果传入的命令带有空格则会导致执行失败。 */
process.start("hello world.exe");
qDebug()
输出:
"hello"
start函数2
void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
{
...
d->program = program;
d->arguments = arguments;
d->start(mode);
}
简单使用小例子:
QProcess process;
/* 由于硬是传入空参数列表QStringList(),使得传入的program不用分解,有空格也无所谓。 */
process.start("hello world.exe", QStringList());
qDebug()
输出:
"hello world.exe"
总结
start函数1和start函数2的区别是后者不会对传入的字符串进行分解,而前者会对字符串进行分解(主要为了分解出参数)。那就意味着带有空格路径的应用程序在使用start函数1则会执行不成功,会被程序误以为空格分隔的参数。
使用start函数2的方法可以避免带有空格的应用程序执行失败的影响。但这样带有一个空参数列表的方法看起来感觉不好,也莫名奇妙。我们正确做法应该是这样:
QProcess process;
/* 如执行路径或程序名字带有空格应该使用三个"包含着。 */
process.start("""hello world.exe""");
领取专属 10元无门槛券
私享最新 技术干货