2016-12-01 101 views
0

我想寫位域結構到文件然後讀取它。寫入/讀取位域結構到/從文件

例如:

typedef struct{ 
    ushort 
       a:4, 
       b:4, 
       c:4, 
       d:4; 
} teststruct; 

我試着寫和讀像這樣

QDataStream &operator <<(QDataStream &st, const teststruct &a) 
{ 
    st <<a.a << a.b << a.c << a.d; 
    return st; 
} 

QDataStream &operator >>(QDataStream &st, teststruct &a) 
{ 
    st >>a.a >> a.b >> a.c >> a.d; 
    return st; 
} 

teststruct str1, str2; 
str1.a = 1; 
str1.b = 0; 
str1.c = 1; 
str1.d = 0; 

QFile f("testfile"); 
f.open(QFile::WriteOnly); 
QDataStream st(&f); 

st << str1; 
f.close(); 
f.open(QFile::ReadOnly); 
QDataStream st(&f); 
st >> str2; 
f.close(); 

QDataStream::operator>>我得到一個錯誤,我可以做

error: cannot bind bitfield 'a.teststruct::a' to 'quint16& {aka short unsigned int&}'

什麼用>>或者也許有其他方式來讀取數據到我的結構?

+0

不能有一個非const引用到一個比特領域。 'QDataStream :: operator >>(quint16&i)'把參數作爲非const引用(因爲你得到的錯誤信息顯示),這就是爲什麼你會得到錯誤。 – thuga

回答

0

在您的示例中,您應該注意保存到文件的數據可能不正確。因此,例如,具有以下結構:

struct BitStruct 
{ 
    uint8_t  b1:4; 
    uint8_t  b2:4; 
}; 

和操作寫成:當你寫的樣本數據BitStruct bits{0x1, 0x2};到文件,你將有寫2個字節

QDataStream &operator <<(QDataStream &st, const BitStruct &a) 
{ 
    st <<a.b1 << a.b2; 
    return st; 
} 

。該文件的二進制內容將爲0x01 0x02,這可能不是您想要實現的內容。

它發生是由於這樣的事實,呼籲st << a.b1導致b1場被轉換成由QDataStream處理的類型之一,在這種情況下,最有可能是quint8(你可以在docs閱讀更多)。

要解決此問題,您可以修改QDataStream::operator<<實施:

st.writeRawData(reinterpret_cast<const char*>(&a), sizeof(BitStruct)); 

在另一方面,讀取數據,以這樣的結構,你應該做一個類似的更新在QDataStream::operator>>實現:

st.readRawData(reinterpret_cast<char*>(&a), sizeof(BitStruct)); 

這將允許按照預期以緊湊的方式寫入結構並相應地讀取特定的位字段。

通過這種方式,您可以用一種方法編寫/讀取整個結構,而且您不必擔心結構(附加字段)的進一步增長並更新兩個運算符實現。

0

我認爲你有位域結構的原因是它的大小是ushort(真的uint16_t),並且按值傳遞它很便宜,並且它佔用了最小的空間。這是一個好的理由,讓我們一起去吧。

請注意,結構的內存中佈局與其磁盤佈局沒有任何關係!磁盤上的佈局取決於您如何使用QDataStream及其運營商。當你顯示它浪費的空間75%的盤佈局 - 各值取16位,但它僅需要4:

(uint16_t a) (uint16_t b) (uint16_t c) (uint16_t d) 

關鍵修復它是使用中間值作爲結構和之間的界面數據流。

因此:

QDataStream &operator <<(QDataStream &st, const teststruct &a) 
{ 
    uint8_t v0 = (a.d << 4) | a.c; 
    uint8_t v1 = (a.b << 4) | a.a; 
    st << v0 << v1; 
    return st; 
} 

QDataStream &operator >>(QDataStream &st, teststruct &a) 
{ 
    uint8_t v0, v1; 
    st >> v0 >> v1; 
    a.a = v1; 
    a.b = v1>>4; 
    a.c = v0; 
    a.d = v0>>4; 
    return st; 
} 

磁盤上的佈局現在沒有浪費的空間,並且是如下(使用假型):

[(uint4_t d) (uint4_t c)] [(uint4_t b) (uint4_t a)]