سؤال

أنا أنظر إلى مكتبة C# تسمى Bitstream, ، الذي يسمح لك بكتابة وقراءة أي عدد من البتات إلى C# Stream هدف. لقد لاحظت ما بدا لي قرار تصميم غريب:

عند إضافة أجزاء إلى بايت فارغ ، تتم إضافة البتات إلى MSB من البايت. علي سبيل المثال:

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

ومع ذلك ، عند الرجوع إلى البتات في رقم مثل إدخال, ، الجزء الأول من رقم الإدخال هو LSB. علي سبيل المثال

//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)

يبدو أنه غير متسق بالنسبة لي. منذ ذلك الحين ، عندما نسخ بايت "تدريجياً" كما هو الحال في المثال السابق (الأجزاء الأربعة الأولى ، ثم الأجزاء الأربعة الأخيرة) ، لن نحصل على البايت الأصلي. نحتاج إلى نسخه "للخلف" (أولاً في آخر أربعة بتات ، ثم الأجزاء الأربعة الأولى).

هل هناك سبب لهذا التصميم الذي أفتقده؟ أي تنفيذ آخر لتيارات البتات مع هذا السلوك؟ ما هي اعتبارات التصميم لذلك؟

يبدو أن ffmpeg يتصرف Bitstream بطريقة أعتبرها متسقة. انظر إلى المبلغ الذي يغير البايت من قبل ORجي مع src مؤشر في ال put_bits وظيفة.

كملاحظة جانبية:

الأول بايت إضافة ، هو البايت الأول في صفيف البايت. علي سبيل المثال

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
هل كانت مفيدة؟

المحلول

فيما يلي بعض الاعتبارات الإضافية:

في حالة المنطق - هناك حاجة إلى بت واحد فقط لتمثيل صحيح أو خطأ. عندما تتم إضافة هذا البت إلى بداية الدفق ، يكون دفق البت هو "1." عندما تقوم بتمديد هذا الدفق إلى طول البايت ، فإنه يفرض حشوة بت الصفر حتى نهاية التيار ، على الرغم من أن تلك البتات لم تكن موجودة في الدفق لتبدأ. الموضع في الدفق هو معلومات مهمة تمامًا مثل قيم البتات ، ودفقًا صغيرًا من "1000000" أو 0x80 يحمي توقع أن يكون للقراء اللاحقون أن يكونوا البت الأول الذي يقرؤونه هو الجزء الأول الذي تمت إضافته.

ثانياً ، تتطلب أنواع البيانات الأخرى مثل الأعداد الصحيحة المزيد من البتات لتمثيلها بحيث ستشغل مساحة أكبر في الدفق أكثر من المنطقية. يمكن أن يكون خلط أنواع بيانات الحجم المختلفة في نفس الدفق أمرًا صعبًا للغاية عندما لا تكون محاذاة على حدود البايت.

أخيرًا ، إذا كنت على Intel X86 ، فإن بنية وحدة المعالجة المركزية الخاصة بك هي "Little-Endian" مما يعني LSB أولاً كما تصفك. إذا كنت بحاجة إلى تخزين القيم في الدفق باعتباره endian كبيرًا ، فستحتاج إلى إضافة طبقة تحويل في الكود الخاص بك - على غرار ما أظهرته أعلاه حيث تدفع بايت واحد في كل مرة في الدفق بالترتيب الذي تريده . هذا أمر مزعج ، ولكن مطلوب عادة إذا كنت بحاجة إلى interop مع صناديق Unix الكبيرة أو قد تكون مطلوبة من خلال مواصفات البروتوكول.

امل ان يساعد!

نصائح أخرى

هل هناك سبب لهذا التصميم الذي أفتقده؟ أي تنفيذ آخر لتيارات البتات مع هذا السلوك؟ ما هي اعتبارات التصميم لذلك؟

أشك في أن هناك أي معنى كبير وراء السليل. من الناحية الفنية ، لا يهم طالما أن الكاتب والقارئ يتفقان على الطلب.

وأنا أتفق مع Elazar.

كما يشير/هي ، هذه هي الحالة التي لا يتفق فيها القارئ والكاتب على طلب بت. في الواقع ، فهي غير متوافقة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top