سؤال

لدي مجموعة من 128 منطقية تمثل البتات. كيف يمكنني تحويل هذه التمثيلات 128 بت إلى 16 بايت؟

مثال:

لدي مجموعة تبدو وكأنها هذه:

0110001100110000100010111011001011010011010001010001101101001100
1000010000000000001000111111111101000011111001111011111011111001

(تحويلها إلى 1s و 0s لتكون أكثر إيجازا)

أحتاج إلى تحويل هذه البتات إلى صفيف البايت التالي:

99 48 139 178 211 69 27 76 132 0 35 255 67 231 190 249

تحرير: هذا لا يبدو أن العمل:

public byte[] ToByteArray() {
    int numBytes = Count / 8;

    if (_bits.Count % 8 != 0) numBytes++;

    byte[] bytes = new byte[numBytes];

    int byteIndex = 0, bitIndex = 0;

    for (int i = 0; i < _bits.Count; i++) {
        if (_bits[i])
            bytes[byteIndex] |= (byte)(1 << bitIndex);

        bitIndex++;
        if (bitIndex == 8) {
            bitIndex = 0;
            byteIndex++;
        }
    }

    return bytes;
}

مخرجاتها:

198 12 209 77 203 162 216 50 33 0 196 255 194 231 125 159
هل كانت مفيدة؟

المحلول

يعالج الرمز القليل من الكلمة المنخفضة، لذلك ينتهي بك الأمر مع كل كلمة عكس. كإصلاح سريع وقذر، جرب هذا:

bytes[byteIndex] |= (byte)(1 << (7-bitIndex));

التي تضع القليل في الصفيف في أعلى موقع في البايت الأول، إلخ.

نصائح أخرى

لا أعرف إذا كانت هناك طريقة تلقائية للقيام بذلك، لكن يمكنك القيام بذلك بمختوارات بسيطة.

خوارزمية بسيطة:

  1. قم بإنشاء مجموعة من البايتات التي سيتم استخدامها كمخزن مؤقت للمخرجات، وتهيئة جميع البايتات إلى 0. يجب أن يستند حجم هذه الصفيف إلى طول صفيف المدخلات الخاصة بك: Ceil (bool_array_length / 8.0)

  2. قم بإعلان متغير فهرس لاستخدامه ك byte الحالي الخاص بك، وقم بتعيينه على 0. هذا يحمل الفهرس في مخزن مؤقت الإخراج الخاص بك.

  3. تكرر أكثر من كل عنصر في صفيف مدخلات منطقية.
    3.1. تحول البت الأيسر رقم 1 بواسطة مؤشر الصفيف وزارة الدفاع 8. اتصل بهذا الرقم قناعك.
    3.2. احسب مؤشر البايت الخاص بك كمؤشر الحالي الخاص بك في الصفيف DIV 8.
    3.3. إذا كان لديك منطقي true قيمة الفهرس الحالي في صفيف المدخل الخاص بك منمق، القيام bitwise OR مع البايت الحالي الخاص بك والقناع الخاص بك.

bool[] bools = ...
BitArray a = new BitArray(bools);
byte[] bytes = new byte[a.Length / 8];
a.CopyTo(bytes, 0);

تحرير: في الواقع هذا أيضا إرجاع:

198 12 209 77 203 162 216 50 33 0 196 255 194 231 125 159

الإخفاء الخاطئ؟ سأترك الإجابة على أي حال، للإشارة.


تحرير: يمكنك استخدام bitarray.copyto () عن طريق عكس المصفوفات مثل ذلك:

bool[] bools = ...
Array.Reverse(bools); // NOTE: this modifies your original array
BitArray a = new BitArray(bools);
byte[] bytes = new byte[a.Length / 8];
a.CopyTo(bytes, 0);
Array.Reverse(bytes);

جرب هذه الوظيفة (مكتوبة كطريقة تمديد).

public byte[] ToByteArray(this bool[] bits)
{
    var bytes = new byte[bits.Length / 8];
    for (int i = 0, j = 0; j < bits.Length; i++, j += 8)
    {
        // Create byte from bits where LSB is read first.
        for (int offset = 0; offset < 8; offset++)
            bytes[i] |= (bits[j + offset] << offset);
    }

    return bytes;
}

ملاحظة: ستفشل إذا لم يكن عدد البتات (المرض) مضاعفا من 8، ولكن الحكم على سؤالك هذا ليس هو الحال. لن يستغرق الأمر سوى طراز صغير جدا للسماح بصفيفات بت من أي طول.

private static byte[] GetBytes(string bitString)
{
    byte[] result = Enumerable.Range(0, bitString.Length / 8).
        Select(pos => Convert.ToByte(
            bitString.Substring(pos * 8, 8),
            2)
        ).ToArray();

    List<byte> mahByteArray = new List<byte>();
    for (int i = result.Length - 1; i >= 0; i--)
    {
        mahByteArray.Add(result[i]);
    }

    return mahByteArray.ToArray();
}

private static String ToBitString(BitArray bits)
{
    var sb = new StringBuilder();

    for (int i = bits.Count - 1; i >= 0; i--)
    {
        char c = bits[i] ? '1' : '0';
        sb.Append(c);
    }

    return sb.ToString();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top