《C++ GUI Qt 4 編程》 筆記(五)

第15章 網絡

QFtp
QHttp

QTcpSocket QSslSocket
QUdpSocket

使用QCoreApplication而不是QApplication以避免連接到QtGui庫

QUrl類提供了一個高級接口,用來提取URL的不同部分,如文件名稱、路徑、協議和端口

當所有請求都已處理完時,QFtp就發射done(bool)信號,bool表明是否有錯誤發生

connect(&ftp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool)));

bool Ftp::getFile(const QUrl& url)
{
	if (!url.isValid())
		return false;

	if (url.scheme() != "ftp")
		return false;

	if (url.path().isEmpty())
		return false;

	QString localFileName = QFileInfo(url.path()).fileName();
	if (localFileName.isEmpty())
		localFileName = "ftpget.out";

	file.setFileName(localFileName);
	if (!file.open(QIODevice::WriteOnly))
		return false;

	ftp.connectToHost(url.host(), url.port(21));
	ftp.login(); // 匿名登錄
	ftp.get(url.path, &file); // 如果要保存到內存中 QBuffer
	ftp.close();
	return true;
}

FTP指令在Qt的事件循環中排隊並等待執行。

void FtpGet::ftpDone(bool error)
{
	// ...
	file.close();
	emit done(); // done()調用app.quit()
}

QFtp提供的FTP指令函數
connectToHost()
login() close() list() cd() get() put() remove()
mkdir() rmdir() rename()

使用rawCommand() 可以執行任意FTP指令
ftp.rawCommand("SITE CHMOD 755 fortune")

QFtp信號
commandStarted(int) // int 指令ID號
commandFinished(int, bool)
stateChanged() // 只要連接進入了一個新狀態就會發射該信號
done(bool) // 一旦指令隊列變空,就會發射這個信號
listInfo(const QUrlInfo&) // 對list()處理的每一個文件調用該信號
如果發生錯誤,QFtp會自動清空指令隊列,錯誤指令後面的指令將不會執行

.pro
QT += network

QUrlInfo urlInfo;
urlInfo.isSymLink()

QBuffer* buffer = new QBuffer;
buffer->open(QIODevice::WriteOnly);
ftp.get(urlInfo.name(), buffer);

QHttp
get() post() 是異步工作的,調用時立即返回,當控制權回到Qt事件循環時纔會開始傳輸數據

connect(&http, SIGNAL(done(bool)), this, SLOT(httpDone(bool)));
http.setHost(url.host(), url.port(80));
http.get(url.path(), &file);
http.close();

http.setHost("www.example.com");
http.post("/cgi/somescript.py", "x=200&y=320", &file);

QHttpRequestHeader header("POST", "/search.html");
header.setValue("Host", "www.trolltech.com");
header.setContentType("application/x-www-form-urlencoded");
http.setHost("www.trolltech.com");
http.request(header, "qt-interest=on&search=opengl");

QHttp貌似在Qt5中已經不存在了

QTcpSocket

// 連接函數會立即返回
tcpSocket.connectToHost("tripserver.zugbahn.de", 6178);
progressBar->show();

連接成功後會發送connected()信號
連接失敗會發送error(QAbstracSocket::SocketError)信號
readyRead()信號 只要QTcpSocket已經從服務器收到新數據,就會發射該信號

QByteArray block;
tcpSocket.write(block); // 基於塊

QTcpServer 信號
incomingConnection(int socketId)

QTcpServer
.listen(QHostAddress::Any, 6178); // any 表示 本地主機上的任意IP地址 0.0.0.0

基於行

QStringList lines;
while (tcpSocket.canReadLine())
	lines.append(tcpSocket.readLine());

發送數據使用QTextStream

QTimer timer;
timer.start(2 * 1000);
connect(&timer, SIGNAL(timeout()), this, SLOT(sendDatagram()));
QByteArray datagram;
QDataStream out(&datagram, QIODevice::WriteOnly);
	out << ... ;
// 不接受主機名稱,只接受主機地址
udpSocket.writeDatagram(datagram, QHostAddress::LockHost, 5824);

QHostInfo::fromName()
QHostInfo::lookupHost()

UTP客戶端

udpSocket.bind(5824);
connect(&udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));

QByteArray datagram;
datagram.resize(udpSocket.pendingDatagramSize());
udpSocket.readDatagram(datagram.data(), datagram.size());

第16章 XML

QtXml模塊的三個不同編程接口
QXmlStreamReader 一個用於讀取格式良好的XML文檔的快速解析器
DOM 將XML文檔轉換爲應用程序可以遍歷的樹形結構
SAX 通過虛擬函數直接嚮應用程序報告解析事件

XML文件寫入,三種方法:
1. 使用QXmlStreamWriter
2. 在內存中以DOM樹的結構表示數據,並要求樹結構將自己寫到文件中
3. 手動生成XML

QXmlStreamReader
.readNext()
.isStartElement()
.isCharacters()

QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text))
	return false;
QXmlStreamReader reader;
reader.setDevice(&file);
reader.readNext();
while (!reader.atEnd())
{
	if (reader.isStartElement())
	{
		if (reader.name() == "bookindex")
			readBookindexElement();
		else
			// 將導致下一次調用atEnd()返回true
			// QFile::error() QFile::errorString()獲得錯誤信息
			reader.raiseError(QObject::tr("Not a bookindex file"));
	}
	else
		reader.readNext();
}

file.close();
if (reader.hasError())
	// reader.errorString()
	return false;
else if (file.error() != QFile::NoError)
	// file.error.String()
	return false;

.pro
QT += xml

QDomDocument doc;
doc.setContent(&file, ...);
QDomElement root = doc.documentElement();
root.tagName();

QDomNode child = element.firstChild();
while (!child.isNull)
{
	child.toElement().tagName();
	child = child.nextSibling();
}

Qt的SAX類時對基於SAX2的java實現的模擬

QXmlSimpleReader
QXmlContentHandler
QXmlErrorHandler
...

繼承自QXmlDefaultHandler
重寫事件處理函數
startDocument()
startElement()
characters()
endElement()
endDocument()
fatalError()

QFile file(fileName);
QXmlInputSource inputSource(&file);
QXmlSimpleReader reader;
reader.setContentHandler(this);
reader.setErrorHandler(this);
reader.parse(inputSource);

XML保存

QXmlStreamWriter自動處理轉義字符

QXmlStreamWriter xmlWriter(&file);
xmlWriter.setAutoFormatting(true);
xmlWriter.writeStartDocument();
xmlWriter.writeStartElement(...);
xmlWriter.writeAttribute();
...
xmlWriter.writeEndElement();
xmlWriter.writeEndDocument();

QDomDocument doc;
doc.save();

// QTextStream::setCodec()
doc.save(..., QDomNode::EncodingFromTextStream);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章