1. 程式人生 > >初探QT序列資料

初探QT序列資料

在處理網路通訊序列資料過程中(這裡主要指socket通訊)序列資料的傳送和解析是一個重要的環節,對於socket通訊常用的傳輸格式為位元組流,所以通訊時資料的序列化處理十分重要。這裡首先說明下對序列資料解析的兩種情況:1,序列資料為基本資料型別;2,序列資料為自定義資料型別如結構體。

QT中處理序列資料常用的類為QDataStream,通過它的介面函式可以輕鬆實現資料的序列化儲存和讀取,這個類通過繫結IO介面(socketIO裝置、檔案等)實現對目標檔案內容的序列操作。儲存原始二進位制檔案的常用類為QByteArray,這個類不是從IODevice繼承過來的,但可以通過QDataStream

實現資料的儲存與操作。下面說明下使用過程和存在的坑!

1:通過QDataStreamQByteArray寫入字串

通過QDataStreamQByteArray中寫入QString,檢視記憶體中資料儲存情況。發現儲存的資料與預想的不一樣,QString的儲存資料格式在頭部4個位元組表示資料的總長度(位元組),最後沒有“0”來代表字串的結束,QString型別下的“test”字串資料總長度達到12位元組!程式碼如下:

結果:

前四個位元組0x00 0x00 0x00 0x08 表示後續字串資料的長度為8,後面8個位元組為具體的字串內容0x00 0x74 0x00 0x65 0x00 0x73 0x00 0x74至於為什麼為8個位元組儲存4

個字元與編碼有關,QT中的QString採用16位元組來編碼字元。

再驗證一次:


結果:


恩,不出所料和預想的一樣,下一個QString("again")儲存過程中又增加了4位元組的頭!這是QString進行跨平臺通訊時需要注意的,否則解析資料時容易出錯。那const char在QT中的儲存結構有什麼變化嗎,我試了一下:


結果:


這裡可以發現對於const char,不但儲存結構中前4個位元組儲存了後續資料的位元組長度,而且在字元資料的末端添加了一個“0”作為字串的終止符號,但是呢,這裡因為是char型別,所以資料儲存為8位,資料的總長度反而降低了。

2、基本型別資料在QByteArray中的儲存

瞭解了字串的在QT中的儲存格式問題下面看看其他基本型別的儲存過程,這裡以intdouble為例,首先看看int的儲存,依舊先上圖:


結果:


可以看到儲存的資料為4個位元組,沒有額外的附加資料,但是解析的結果出現問題!!!仔細觀察可以發現原來是因為資料的儲存是大端格式(高位位元組在低位記憶體位置)而我的電腦是小端,所以需要大小端轉換,本來不用這麼麻煩,為了理解原理,這裡自己就用最笨的辦法試驗了一下:

結果:

恩,這麼笨而傳統的辦法當然是沒有任何問題了。對於double也存在這樣的問題,可以類似的方法處理:



結果嘛:


直接通過QDataStream設定資料的大小端,這個樣就可以在複製記憶體的時候不用考慮大小端的轉換問題了。網路通訊過程中預設為大端傳輸,值得注意的是,QByteArray通過QFile完成與QDataStream的互動,所以每次寫入時指標都在末尾,從頭讀出需要seek(0)到資料內容的頭部。




可以看到結果沒有任何問題。初次接觸QT的序列資料處理,小小的總結一下。