Qt FTP地址下载中文乱码问题
前言
最近在做Qt项目,使用FTP下载,需要存储ftp地址,ftp地址中文直接复制出现乱码如下:
正常:ftp://127.0.0.1/公共资料区
复制:ftp://127.0.0.1/%E5%85%AC%E5%85%B1%E8%B5%84%E6%96%99%E5%8C%BA
一、为什么乱码?
FTP使用URL的格式记录地址,将中文编码成%形式,可以查看url编码,网上有url编码在线工具很方便查看。
二、解决办法
1.使用QUrl的编码和解码函数
QUrl::fromPercentEncoding(tmp_ba);
QUrl::toPercentEncoding(tmpStrFtpAddr, “😕%”);
经过摸索直接用似乎有点问题于是各种百度最后编写自己的解码函数(url编码–>中文)
QString MainWindow::DecodeURL(QString StrFtpAddr) {
bool haveChinese = StrFtpAddr.contains(QRegExp("[\\x4e00-\\x9fa5]+"));//判断是否有中文,有中文说明不用转化,不是url编码
if (!haveChinese) {
QByteArray tmp_ba = StrFtpAddr.toLocal8Bit();
tmp_ba = tmp_ba.toPercentEncoding(":/%");
QString tmpStrFtpAddr = QUrl::fromPercentEncoding(tmp_ba);
QString tmpStrFtpAddr2 = QUrl::toPercentEncoding(tmpStrFtpAddr, ":/%");
if (tmpStrFtpAddr2 == StrFtpAddr) {
} else {
tmpStrFtpAddr = FromSpecialEncoding(StrFtpAddr);
//qDebug() << tmpStrFtpAddr2;
}
return tmpStrFtpAddr;
} else {
return StrFtpAddr;
}
}
2.使用时遇到的其他问题
ftp中文地址->url方式编码地址有两种:
中文:公共资料区
1.utf8中文->url编码:%E5%85%AC%E5%85%B1%E8%B5%84%E6%96%99%E5%8C%BA
2.gbk中文->url编码:%B9%AB%B9%B2%D7%CA%C1%CF%C7%F8
可以看到gbk,utf8编码的中文对应url地址不一样,这样url解码时需要判断时gbk的方式还是utf8的方式。
我这里就简单的先使用utf8方式解码再编码(str->utf8解码=中文str,中文str->utf8编码),对比前后的是不是一样的来判断是否为utf8中文,(qt url编码按照utf8来编码的)然后在进行gbk-utf8转码
以下函数实现自动识别(gbk或utf8)url编码,并转化为中文utf8格式
QString MainWindow::DecodeURL(QString StrFtpAddr) {
bool haveChinese = StrFtpAddr.contains(QRegExp("[\\x4e00-\\x9fa5]+"));
if (!haveChinese) {
QByteArray tmp_ba = StrFtpAddr.toLocal8Bit();
tmp_ba = tmp_ba.toPercentEncoding(":/%");
QString tmpStrFtpAddr = QUrl::fromPercentEncoding(tmp_ba);
QString tmpStrFtpAddr2 = QUrl::toPercentEncoding(tmpStrFtpAddr, ":/%");
if (tmpStrFtpAddr2 == StrFtpAddr) {
} else {
tmpStrFtpAddr = FromSpecialEncoding(StrFtpAddr);
//qDebug() << tmpStrFtpAddr2;
}
return tmpStrFtpAddr;
} else {
return StrFtpAddr;
}
}
//将gbk编码的字符串改为UTF-8编码,在获取FTP服务器下文件时使用
QString MainWindow::FromSpecialEncoding(QString str) {
QByteArray array;
for (int i = 0; i < str.length();) {
if (0 == QString::compare(str.mid(i, 1), QString("%"))) {
if ((i + 2) < str.length()) {
array.append(str.mid(i + 1, 2).toShort(0, 16));
i = i + 3;
} else {
array.append(str.mid(i, 1));
i++;
}
} else {
array.append(str.mid(i, 1));
i++;
}
}
QTextCodec *code = QTextCodec::codecForName("GBK");
//QTextCodec *utf8 = QTextCodec::codecForName("UTF-8");
return code->toUnicode(array);
//return utf8->fromUnicode(code->toUnicode(array));
}
使用ftp地址时,再将保存的中文进行编码,可能遇到url解码出现很多%25问题,下面函数可以解决
/*ftp下载文件*/
void MyFtpOp::ftpDownload(const QString &fileName)
{
QFileInfo info;
info.setFile(fileName);
m_file.setFileName(fileName);
m_file.open(QIODevice::WriteOnly | QIODevice::Append);
m_manager = new QNetworkAccessManager(this);
m_manager->setNetworkAccessible(QNetworkAccessManager::Accessible);
/*ftp地址编码转换*/
mFtpPath = DecodeURL(mFtpPath);
m_url.setPath(ToSpecialEncoding(mFtpPath));
qDebug() << m_url;
pReply = m_manager->get(QNetworkRequest(m_url));
connect(pReply, SIGNAL(readyRead()), this, SLOT(readContent()));
connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
connect(pReply, SIGNAL(downloadProgress(qint64, qint64)), this, SIGNAL(downloadProgress(qint64, qint64)));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SIGNAL(error(QNetworkReply::NetworkError)));
}
//将UTF-8编码的字符串改为gbk编码,在由客户端上传或下载文件时使用
QString MyFtpOp::ToSpecialEncoding(const QString &InputStr)
{
#ifdef Q_OS_WIN
return QString::fromLatin1(InputStr.toLocal8Bit());
#else
QTextCodec *codec= QTextCodec::codecForName("gbk");
if (codec)
{
return QString::fromLatin1(codec->fromUnicode(InputStr));
}
else
{
return QString("");
}
#endif
}
总结
了解:1.Url编码方式gbk,utf8两种;2.gbk-utf8转码
自己各种百度花了不少时间,留个笔记
时间:2022.04.14