對於純綷的二進位資料,可以使用QDataStream來協助處理,可以直接處理C++基本資料型態、還有許多Qt資料型態,像是QByteArray、QString、QMap等,可以使用 << 或 >> 運算子來進行資料輸出或寫入。
先使用以下的簡單例子,示範一下QDataStream搭配QFile來進行檔案讀寫:
#include <QFile>
#include <QDataStream>
#include <QString>
#include <QMap>
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {  
    QFile file("data.dat");
    
    QMap<QString, int> map;
    map.insert("caterpillar", 95);
    map.insert("momor", 93);
    
    if(!file.open(QIODevice::WriteOnly)) {
        cerr << "Cannot open file for writing: "
             << qPrintable(file.errorString()) << endl;    	
    	return false;
    }
    
    QDataStream out(&file);
    // 設定QDataStream支援版本
    out.setVersion(QDataStream::Qt_4_3);
    
    // 寫入資料
    out << 1 << map;
    file.close();
    
    if(!file.open(QIODevice::ReadOnly)) {
        cerr << "Cannot open file for reading: "
             << qPrintable(file.errorString()) << endl;    	
    	return false;
    }    
    
    QDataStream in(&file);
    // 設定QDataStream支援版本
    in.setVersion(QDataStream::Qt_4_3);
    
    int num = 0;
    QMap<QString, int> inMap;
    // 讀入資料
    in >> num >> inMap;
    cout << "num: " << num << endl
         << "map: <caterpillar, " << inMap.value("caterpillar") << ">" << endl
         << "map: <momor, " << inMap.value("momor") << ">" << endl;
    
    return true;
}程式中可以看到setVersion()方法,這設定QDataStream讀寫時的版本,因為Qt的物件成員等資料,會隨著不同版本而可能有所不同,例如QMap新版中可能有一些成員屬性是舊版本所沒有的,使用setVesrion()設定Qt支援的讀寫版本,告訴QDataStream在寫入或讀取時應當處理的物件資料。
程式執行時的結果如下所示:
num: 1
map: <caterpillar, 95>
map: <momor, 93>
            
      map: <caterpillar, 95>
map: <momor, 93>
QDataStream也可以直接處理位元資料,例如使用 readRawBytes()與writeRawBytes()來進行原始位元資料的處理。QDataStream處理數值時,預設使用big- endian的方式,如果您要改變為使用little-endian,則可以使用setByteOrder()方法設定為QDataStream:: LittleEndian。
如果想要QDataStream可以使用 << 或 >> 來支援您的自訂義物件,則您需要重載 << 與 >> 運算子,告訴QDataStream如何儲存或讀取物件,例如:
#include <QFile>
#include <QDataStream>
#include <QString>
#include <iostream>
using namespace std;
class Dog {
public:
	Dog() { _number = 0; }
	
	Dog(int number, const QString &name) {
		_number = number;
		_name = name;
	}
	
	void setNumber(int number) { _number = number; }
    int number() const { return _number; }
	
	void setName(const QString &name) { _name = name; }
    QString name() const { return _name; }
private:
	int _number;
	QString _name;
};
QDataStream &operator<<(QDataStream &out, const Dog &dog) {
    out << dog.number() << dog.name();
    return out;
	
}
QDataStream &operator>>(QDataStream &in, Dog &dog) {
	int number = 0;
	QString name;
	
	in >> number >> name;
	
	dog.setNumber(number);
	dog.setName(name);
	return in;
}
int main(int argc, char *argv[]) {  
    QFile file("data.dat");
    
    Dog dog1(1, "caterpillar");
    Dog dog2(2, "momor");
    
    if(!file.open(QIODevice::WriteOnly)) {
        cerr << "Cannot open file for writing: "
             << qPrintable(file.errorString()) << endl;    	
    	return false;
    }
    
    QDataStream out(&file);
    out.setVersion(QDataStream::Qt_4_3);
    out << dog1 << dog2;
    file.close();
    
    if(!file.open(QIODevice::ReadOnly)) {
        cerr << "Cannot open file for reading: "
             << qPrintable(file.errorString()) << endl;    	
    	return false;
    }    
    
    QDataStream in(&file);
    in.setVersion(QDataStream::Qt_4_3);
    
    in >> dog1 >> dog2;
    cout << dog1.number() << ", " << qPrintable(dog1.name()) << endl 
         << dog2.number() << ", " << qPrintable(dog2.name()) << endl;
         
    return true;
}程式執行時的結果如下所示:
1, caterpillar
2, momor
            
      2, momor
如以上重載 << 與 >> 運算子,還有一個好處,就是可以讓自定義物件支援QList等容器之 << 與 >> 之附加與取出,例如像以下的操作:
QList<Dog> list;
          
Dog dog1(1, "caterpillar");
Dog dog2(2, "momor");
          
list << dog1 << dog2;
          
QList<Dog>::const_iterator iterator = list.begin();
          
while(iterator != list.end()) {
cout << (*iterator).number() << ", "
<< qPrintable((*iterator).name()) << endl;
++iterator;
}
      
      Dog dog1(1, "caterpillar");
Dog dog2(2, "momor");
list << dog1 << dog2;
QList<Dog>::const_iterator iterator = list.begin();
while(iterator != list.end()) {
cout << (*iterator).number() << ", "
<< qPrintable((*iterator).name()) << endl;
++iterator;
}

