2009-09-08 12 views
5

Ich schaue auf die C# -Bibliothek mit dem Namen BitStream, mit der Sie eine beliebige Anzahl von Bits zu einem Standard C# Stream Objekt schreiben und lesen können. Ich bemerkte, was mir eine seltsame Designentscheidung schien:Entwerfen eines BitStream in C#

Wenn Bits einem leeren Byte hinzugefügt werden, werden die Bits dem MSB des Bytes hinzugefügt. Zum Beispiel:

var s = new BitStream(); 
s.Write(true); 
Debug.Assert(s.ToByteArray()[0] == 0x80); // and not 0x01 

var s = new BitStream(); 
s.Write(0x7,0,4); 
s.Write(0x3,0,4); 
Debug.Assert(s.ToByteArray()[0] == 0x73); // and not 0x37 

Wenn jedoch Bits in einer Reihe als Eingang , das erste Bit der Eingangsnummer Referenzierung ist das LSB. Zum Beispiel

//s.Write(int input,int bit_offset, int count_bits) 
//when referencing the LSB and the next bit we'll write 
s.Write(data,0,2); //and not s.Write(data,data_bits_number,data_bits_number-2) 

Es scheint mir inkonsistent. Da in diesem Fall beim "allmählichen" Kopieren eines Bytes wie im vorherigen Beispiel (die ersten vier Bits und dann die letzten vier Bits) das ursprüngliche Byte nicht erhalten wird. Wir müssen es "rückwärts" kopieren (zuerst die letzten vier Bits, dann die ersten vier Bits).

Gibt es einen Grund für dieses Design, das ich vermisse? Jede andere Implementierung von Bit-Stream mit diesem Verhalten? Was sind die Design-Überlegungen dafür?

Es scheint, dass ffmpeg Bitstream in einer Weise verhält, die ich als konsistent betrachte. Sehen Sie sich den Betrag an, um den das Byte vor OR mit dem Zeiger src in the put_bits function verschoben wird.

Als Nebenbemerkung:

Das erste Byte zugegeben wird, ist das erste Byte in den Byte-Array. Zum Beispiel

var s = new BitStream(); 
s.Write(0x1,0,4); 
s.Write(0x2,0,4); 
s.Write(0x3,0,4); 
Debug.Assert(s.ToByteArray()[0] == 0x12); // and not s.ToByteArray()[1] == 0x12 

Antwort

3

Hier sind einige zusätzliche Überlegungen:

Im Falle der Booleschen - nur ein Bit erforderlich ist, wahr oder falsch darzustellen. Wenn dieses Bit am Anfang des Streams hinzugefügt wird, ist der Bitstrom "1". Wenn Sie diesen Stream auf Bytelänge erweitern, erzwingt er das Auffüllen von Null-Bits an das Ende des Streams, obwohl diese Bits nicht im Stream vorhanden waren, um damit zu beginnen. Die Position in dem Strom ist eine wichtige Information, genau wie die Werte der Bits, und ein Bitstrom von "1000000" oder 0x80 stellt die Erwartung sicher, dass nachfolgende Leser des Stroms das erste Bit haben, das sie lesen, ist das erste Bit, das hinzugefügt wurde.

Zweitens, andere Datentypen wie Ganzzahlen erfordern mehr Bits zu repräsentieren, so dass sie mehr Platz in den Stream als Booleans belegen werden. Das Mischen von Datentypen unterschiedlicher Größe in demselben Stream kann sehr schwierig sein, wenn sie nicht an Bytegrenzen ausgerichtet sind.

Schließlich, wenn Sie auf Intel x86 sind Ihre CPU-Architektur ist "Little-Endian" was bedeutet, LSB zuerst wie Sie beschreiben. Wenn Sie Werte im Stream als Big-Endian speichern möchten, müssen Sie in Ihrem Code eine Konvertierungsebene hinzufügen - ähnlich wie oben gezeigt, wenn Sie in der gewünschten Reihenfolge jeweils ein Byte in den Stream schieben .Dies ist ärgerlich, wird aber häufig benötigt, wenn Sie mit Big-Endian-Unix-Boxen interoperieren müssen oder eine Protokollspezifikation dies erfordert.

Hoffe, dass hilft!

1

Gibt es einen Grund für das Design, die ich vermisst habe? Jede andere Implementierung von Bit-Stream mit diesem Verhalten? Was sind die Design-Überlegungen dafür?

Ich bezweifle, dass es eine signifikante Bedeutung hinter der Entscheidung gab. Technisch ist es egal, solange der Autor und der Leser sich auf die Reihenfolge einigen.

+0

Es scheint mir inkonsequent. Da in diesem Fall, wenn "allmählich" Aber ich habe nur gezeigt, dass es wichtig ist. Quote: "Kopieren wir ein Byte wie im vorherigen Beispiel (die ersten vier Bits und dann die letzten vier Bits), erhalten wir nicht das ursprüngliche Byte. Wir müssen es" rückwärts "kopieren (zuerst die letzten vier Bits, dann die ersten vier Bits). " –

+0

Wie gesagt, wenn Leser und Autor sich auf die Bit-Reihenfolge einigen, spielt es keine Rolle. IMO sollten Sie den BitStream zum Lesen und Schreiben verwenden. Wenn Sie andere Absichten haben, wie das Lesen der resultierenden Bytes, sollten Sie wahrscheinlich nur Ihren eigenen Stream schreiben. –

1

Ich stimme Elazar zu.

Wie er/sie darauf hinweist, ist dies ein Fall, in dem der Leser und der Schriftsteller NICHT über die Bit-Reihenfolge einig sind. In der Tat sind sie nicht kompatibel.