typedef uint64_t u36;
現在,無論你的系統是否使用大端或小端,你可以寫值到二進制流以一個可預測的順序執行,一次執行一個字節。讓我們使用big-endian,因爲稍微更容易將組裝在一起的圖像繪製成價值。
你可以使用天真的移位和掩碼到一個小緩衝區。唯一要決定的是截斷半字節的地方。但是如果遵循將每個值移位另外8位的模式,則其餘部分自然會處於高位。
ostream & write_u36(ostream & s, u36 val)
{
char bytes[5] = {
(val >> 28) & 0xff,
(val >> 20) & 0xff,
(val >> 12) & 0xff,
(val >> 4) & 0xff,
(val << 4) & 0xf0
};
return s.write(bytes, 5);
}
但是,這不是你如何寫一堆這些數字。在完成之前,您必須暫停第5個字節,否則您可以將下一個值打包。或者,你總是在同一時間寫兩個值:
ostream & write_u36_pair(ostream & s, u36 a, u36 b)
{
char bytes[9] = {
(a >> 28) & 0xff,
(a >> 20) & 0xff,
(a >> 12) & 0xff,
(a >> 4) & 0xff,
(a << 4) & 0xf0 | (b >> 32) & 0x0f,
(b >> 24) & 0xff,
(b >> 16) & 0xff,
(b >> 8) & 0xff,
b & 0xff
};
return s.write(bytes, 9);
}
所以現在,你可能會看到如何去閱讀值和deserialising它們放回整數。最簡單的方法是一次讀兩個。
istream & read_u36_pair(istream & s, u36 & a, u36 & b)
{
char bytes[9];
if(s.read(bytes, 9))
{
a = (u36)bytes[0] << 28
| (u36)bytes[1] << 20
| (u36)bytes[2] << 12
| (u36)bytes[3] << 4
| (u36)bytes[4] >> 4;
b = ((u36)bytes[4] & 0x0f) << 32
| (u36)bytes[5] << 24
| (u36)bytes[6] << 16
| (u36)bytes[7] << 8
| (u36)bytes[8];
}
return s;
}
如果你想讀他們一次一個,你需要保留一些狀態的跟蹤,所以你知道如何讀取的字節數(5或4),以及移位操作應用。像這樣的天真幼稚:
struct u36deser {
char bytes[5];
int which = 0;
};
istream & read_u36(istream & s, u36deser & state, u36 & val)
{
if(state.which == 0 && s.read(state.bytes, 5))
{
val = (u36)state.bytes[0] << 28
| (u36)state.bytes[1] << 20
| (u36)state.bytes[2] << 12
| (u36)state.bytes[3] << 4
| (u36)state.bytes[4] >> 4;
state.which = 1;
}
else if(state.which == 1 && s.read(state.bytes, 4))
{
val = ((u36)state.bytes[4] & 0x0f) << 32 // byte left over from previous call
| (u36)state.bytes[0] << 24
| (u36)state.bytes[1] << 16
| (u36)state.bytes[2] << 8
| (u36)state.bytes[3];
state.which = 0;
}
return s;
}
所有這些都是純粹的假設,無論如何,這似乎是你的問題的關鍵。還有很多其他的方式來串行化位,其中一些並不明顯。
完全由您來決定一個字節中的哪些位首先出現。 –
你將需要聲明'readHere'爲'uint64_t'(或更大的東西),以便在其中存儲5個字節。 – TriskalJM
是的,忘了它,謝謝我會修復它。 – Darlyn