记录在使用 QT 开发过程中碰到的关于 QSetting 编写配置文件读写中文的问题,QProcess command 路径中存在中文的问题,以及使用 QString 转 std::string 时,原QString携带中文的问题
QProcess::startDetached() 或者 start() command路径中空格问题
在开发过程中遇到一个重启客户端的问题失败的问题
错误示例:
QString filepath = qApp->applicationFilePath();
QProcess::startDetached(filepath);
当路径中没有空格是没有问题,但是当程序安装在 D:\Program Files
路径下,这一段代码就会失效
更正
QString infilepath = qApp->applicationFilePath();
infilepath = infilepath.replace("/","\\");
QString filepath = "\"" + infilepath + "\"";
QProcess::startDetached(filepath);
为了找到空格具体影响的原因,需要看一下 QProcess::startDetached(const QString &command)
这个函数的源码
bool QProcess::startDetached(const QString &command)
{
QStringList args = parseCombinedArgString(command);
if (args.isEmpty())
return false;
const QString prog = args.takeFirst();
return QProcessPrivate::startDetached(prog, args);
}
从这里可以看出,解析 command 可能出现问题, 因为一个 cmd 命名可以分为2部分,一部分为 prog 应用程序部分,另一部分是 args 参数,所以接下来主要是看 static QStringList parseCombinedArgString(const QString &program)
这个函数
static QStringList parseCombinedArgString(const QString &program)
{
QStringList args;
QString tmp;
int quoteCount = 0;
bool inQuote = false;
// 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 < program.size(); ++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);
}
}
if (!tmp.isEmpty())
args += tmp;
return args;
}
从这一段代码可以看出,先判断 "
双引号,双引号不会存入tmp,(当三个双引号连续,会写入tmp 一个), 并且以 program.at(i).isSpace()
空格来判断 args 的结尾
按照上面代码的规则
以 QString filepath = "D:\\Program Files\\1.exe";
路径为例
最后解析的结果为 D:\Program
和 Files\1.exe
2部分
所以这里有个很简单的解决方案,就是改成 QString filepath = "\"D:\\Program Files\\1.exe\"";
如果携带参数的话 可以用空格将所有参数隔开, QString filepath = "\"D:\\Program Files\\1.exe\" -help";
关于路径中 “\” 和 “/” 的差异我的理解是:
- Windows下使用的是反斜杠 “\”,
- Linux下使用的是正斜杠 “/”
但是在QT里,我用获取路径的函数等得到的 QString 路径用的都是 “/” 正斜杠,可能是因为 “\” 反斜杠是转义字符,所以得到的路径我一般
- 先使用replace(“/”,”\\”)转一下路径中的正斜杠
然后用双引号包一下就可以解决这个问题了
QString infilepath = qApp->applicationFilePath(); infilepath = infilepath.replace(“/”,”\”); QString filepath = “\“” + infilepath + “\“”; QProcess::startDetached(filepath);
最后总结一下
static bool startDetached(const QString &command);
void start(const QString &command, OpenMode mode = ReadWrite);
在使用这2个需要解析指令和参数的函数时,需要注意指令部分需要使用双引号包起来
QSetting 读写中文的问题
读取和设置的时候都需要设置编码格式,settings.setIniCodec(QTextCodec::codecForName("GB2312"));
// 设置
void setValueForSettings(const QString &target, const QVariant &value)
{
QString strFileName = QCoreApplication::applicationDirPath() + "/config.ini" ;
QSettings settings(strFileName, QSettings::IniFormat);
settings.setIniCodec(QTextCodec::codecForName("GB2312"));
settings.setValue(target, value);
}
// 读取
QVariant getValueFromSettings(const QString &target)
{
QString strFileName = QCoreApplication::applicationDirPath() +"/config.ini" ;
QSettings settings(strFileName, QSettings::IniFormat);
settings.setIniCodec(QTextCodec::codecForName("GB2312"));
QVariant value = settings.value(target);
return value;
}
中文路径问题
在使用一些 C 的函数时例如 std::fstream 的 open 时,直接使用 QT 的 toStdString() 函数将 QString 类型转成 std::string 时,只要路径中存在中文,转换出来的新的 std::string 实际上是乱码, C 函数并不能正确使用,这主要是因为 toStdString() 函数本身调用的是 Utf8 的编码, 所以想正确转换, 需要使用 QTextCodec
类,声明转码器为 GBK
或者 GB2312
#include <QTextCodec>
QTextCodec *code = QTextCodec::codecForName("GB2312");//解决中文路径问题
std::string name = code->fromUnicode(dir).data();