1. 程式人生 > >QT---之QDataStream的建構函式使用QByteArray物件注意事項

QT---之QDataStream的建構函式使用QByteArray物件注意事項

QDataStream 的建構函式關於使用QByteArray物件的注意事項

//先上測試程式碼:

#include <QDataStream>

#include <QByteArray>

#include <QFile>

 

int main()

{

    QByteArray dstByteArray;

    QString    strRead;

    

    QDataStream writeToByteArray(&dstByteArray, QIODevice::ReadWrite);

 

    QFile       fConsol; 

    // 開啟控制檯輸出

    fConsol.open(stdout, QIODevice::WriteOnly);

    QTextStream writeTextConsol(&fConsol);

 

    // 向dstByteArray中寫入一個字串

    writeToByteArray << QString("test");

    // 然後再從裡面讀出來

    writeToByteArray >> strRead ;

    // 顯示剛剛的讀取結果

    writeTextConsol << strRead;

 

    return 0;

}

我期望的結果當然是把剛寫入的字串 "test" 讀出來然後再顯示到控制檯上,但是結果卻意外:

QByteArray通過QDataStream的讀寫 - 棲 - 活著

 如圖,結果什麼也沒有,為什麼呢?????

查下qt的文件,看了QDataStream的建構函式介紹:

QDataStream::QDataStream ( QByteArray * a, QIODevice::OpenMode mode )

Constructs a data stream that operates on a byte array, a. The mode describes how the device is to be used.

Alternatively, you can use QDataStream(const QByteArray &) if you just want to read from a byte array.

Since QByteArray is not a QIODevice subclass, internally a QBuffer is created to wrap the byte array.

 

從可以看出因為QByteArray不是一個繼承自QIODevice的類所以QDataStream類在處理它的時候會建立一個QBuffer類.而QBuffer是繼承自QIODevice類的,而QIODevice類在處理資料的時候都有一個檔案指標,指向當前處理的位置.當使用

 writeToByteArray << QString("test");向一個QByteArray中寫入一個字串後,就像對檔案的寫入一樣,檔案的指標會向後移動,指向下一個位置,當使用:

writeToByteArray >> strRead ;

再從QByteArray中讀入時,因為此時檔案的指標指在最後面,讀的時候就會發現後面沒有資料了,所以就會返回一個空字串,於是輸出什麼也沒有了.即然知道原因了就好辦了,只要在讀取之前重新設定一下檔案指標就可以了,下面是程式碼:

 

// 省略相同的...........

.

    // 向dstByteArray中寫入一個字串

    writeToByteArray << QString("test");

//-------------------------------------------------------------

    // 設定檔案指標                                // 這裡是新加的

    writeToByteArray.device()->seek(0);

//-----------------------------------------------------------------

    // 然後再從裡面讀出來

    writeToByteArray >> strRead ;

// 省略相同的...........

 

結果:

QByteArray通過QDataStream的讀寫 - 棲 - 活著

 可以看到顯示和預想的一樣了.

 

對於用QDataStream向一個ByteArray中寫入的資料,可不可以直接輸出呢如下:

 

 writeTextConsol << dstByteArray.data();

 

因為data()會返回QByteArray中資料的指標。下面來測試一下:

 

#include <QDataStream>

#include <QTextStream>

#include <QFile>

 

int main()

{

        QByteArray dstByteArray;

        QString    strRead;

        

        QDataStream writeToByteArray(&dstByteArray, QIODevice::ReadWrite);

 

        QFile       fConsol; 

        // 開啟控制檯輸出

        fConsol.open(stdout, QIODevice::WriteOnly);

        QTextStream writeTextConsol(&fConsol);

 

        // 向dstByteArray中寫入一個字串

        writeToByteArray << QString("test");

        // 這裡直接輸出

        writeTextConsol << dstByteArray.data();

 

        return 0;

}

結是是:

QByteArray通過QDataStream的讀寫 - 棲 - 活著

 這又是怎麼回事????????資料是肯定有的,因為前一個例子都可以輸出了。那麼就來看看使用QDataStream向dstByteArray中寫入的資料是什麼樣子的:

 

#include <QDataStream>

#include <QTextStream>

#include <QFile>

 

int main()

{

        QByteArray dstByteArray;

        QString    strRead;

        

        QDataStream writeToByteArray(&dstByteArray, QIODevice::ReadWrite);

 

        QFile       fConsol; 

        // 開啟控制檯輸出

        fConsol.open(stdout, QIODevice::WriteOnly);

        QDataStream writeToConsol(&fConsol);

        QTextStream writeTextConsol(&fConsol);

 

        // 向dstByteArray中寫入一個字串

        writeToByteArray << QString("test");

        // 依次輸出dstByteArray中的字元

        for (int i = 0; i < dstByteArray.length(); i++)

        {

                writeTextConsol << showbase << hex << (int)dstByteArray.at(i) << " ";

        }

        return 0;

}

結果:

QByteArray通過QDataStream的讀寫 - 棲 - 活著

 

0x74 0x65 0x73 0x74 分別對應 test 中的4個字元,那麼怎麼還多了那麼多的0x0呢???要知道答案,看Qt文件吧!!!

下面是QDataStream中看到的一段話:

 a char * string is written as a 32-bit integer equal to the length of the string including the '\0' byte, followed by all the characters of the string including the '\0' byte. When reading a char * string, 4 bytes are read to create the 32-bit length value, then that many characters for the char * string including the '\0' terminator are read.

在使用QDataStream向一個QByteArray中寫入資料時,會首先寫入一個32位的整數,這個整數儲存了了此QByteArray的長度('\0'也算一個字元),當從這個QDataStream中讀QByteArray中的一個字串時會首讀取這個字串中一共有多少個字元,也就是開始的那4個byte,然後再讀取字串的內容。

回到我們的問題上來,從輸出可以看出,開始的4個位元組分別是 00 00 00 08,也就是這個字串的長度是8,一共有8個字元,數一下看看,嗯,真的有8個字元噢。可是我們明明只寫了”test“4個字元啊,怎麼變成了8個字元了呢??????這怎麼莫名其妙的多出4個字元呢???而且還全都是0呢??

這個嘛,因為我們寫的時候是以QString("test")這樣的形式寫入QByteArray中的,而在Qt中QString是以unicode進行編碼的,而unicode編碼的字元是佔兩個位元組的所以呢,4*2剛好是等於8個字元,太好了終於明白了。因為普通的ascii字元中要一個位元組就可以表示了,所以高位元組者以 0 填充,這就是為什麼在0x74 0x65 0x73 0x74 四個字元的前面都多了個 0x0 的原因了。

 

那現在我們不用

writeToByteArray << QString("test");

來寫入資料,而改為下面的這種方式:

writeToByteArray << “test”;

再看輸出結果:

QByteArray通過QDataStream的讀寫 - 棲 - 活著

 

和預想的一樣,哈哈。

前5個字元表示了本字串的長度,後面接的是實際的字串,為什麼長度是5???別忘了QDataStream會把 最後的那個 '\0' 也算進去的噢,你年最後不是多了個0x0麼!!這就是最後的那個 '\0' 。

現在即然知道了前4個字元是表示了字串的長度,那我們可不可以跳過這個長度,當然可以了啊!!

直接這樣寫:

// 省略相同程式碼。。。。。。。。

writeTextConsol << dstByteArray.data() + 4 ;

輸出結果:

QByteArray通過QDataStream的讀寫 - 棲 - 活著

 你看可以吧!!!!

 

學習腳步。。。。。。。。。