سؤال

C#BinaryReader لديه وظيفة وفقًا لـ MSDN ، يقرأ عدد صحيح مشفر على أنه "عدد صحيح سبعة بت" ، ثم يقرأ سلسلة بطول هذا عدد صحيح.

هل هناك وثائق واضحة لتنسيق عدد صحيح سبعة بت (لدي فهم تقريبي بأن MSB أو LSB يمثلون ما إذا كان هناك المزيد من البايتات للقراءة ، والبوت الباقي هي البيانات ، لكنني سأكون سعيدًا لشيء أكثر دقة ).

حتى أفضل ، هل هناك أ C تنفيذ أرقام القراءة والكتابة في هذا التنسيق؟

هل كانت مفيدة؟

المحلول

حسنا ، الوثائق ل BinaryReader.Read7bitenCodedInt يقول بالفعل ، إنه يتوقع كتابة القيمة BinaryWriter.write7bitencodedint وتلك الطريقة توثق التفاصيل التنسيق:

يتم كتابة عدد صحيح لمعلمة القيمة سبعة بت في كل مرة ، بدءًا من البتات السبعة ذات القيمة الصغرى. يشير البايت العالي من البايت إلى ما إذا كان هناك المزيد من البايتات التي يجب كتابتها بعد هذا.

إذا كانت القيمة ستناسب سبعة بت ، فإنها لا تستغرق سوى بايت واحد من المساحة. إذا لم تتناسب القيمة في سبعة بت ، يتم تعيين البت المرتفع على البايت الأول وكتابته. ثم يتم تحويل القيمة بسبعة بتات ويتم كتابة البايت التالي. تتكرر هذه العملية حتى يتم كتابة عدد صحيح بأكمله.

لذلك سيتم تحويل عدد صحيح 1259551277 ، في الثنائي 1001011000100110011101101101 إلى هذا التنسيق 7 بت على النحو التالي:

Remaining integer                 encoded bytes
1001011000100110011101000101101
100101100010011001110100          00101101
10010110001001100                 10101101 01110100
1001011000                        10101101 11110100 01001100
100                               10101101 11110100 11001100 01011000
0                                 10101101 11110100 11001100 11011000 00000100

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

نصائح أخرى

في الأساس ، الفكرة وراء 7 بت مشفرة Int32 هو تقليل عدد البايتات المطلوبة للقيم الصغيرة. يعمل مثل هذا:

  1. يتم أخذ أول 7 أجزاء كبيرة من القيمة الأصلية.
  2. إذا تجاوزت هذه القيمة ما يمكن أن يتناسب مع هذه الأجزاء السبعة ، يتم تعيين البت الثامن على 1 ، مما يشير إلى أن بايت آخر يجب قراءة. وإلا فإن هذا البت هو 0 وينتهي القراءة هنا.
  3. تتم قراءة البايت التالي ، وتحولت قيمتها اليسرى بنسبة 7 بتات و Ored إلى قيمة القراءة سابقًا لدمجها معًا. مرة أخرى ، يشير الجزء الثامن من هذا البايت إلى ما إذا كان يجب قراءة بايت آخر (تحويل قيمة القراءة 7 مرات أخرى).
  4. يستمر هذا حتى يتم قراءة 5 بايت كحد أقصى (لأنه حتى Int32.MaxValue لن يتطلب أكثر من 5 بايت عندما يتم سرقة بت 1 بت فقط من كل بايت). إذا كانت أعلى جزء من البايت الخامس لا تزال محددة ، فقد قرأت شيئًا ليس int32 مشفر 7 بت.

لاحظ أنه نظرًا لأنه مكتوب بايت بايت ، فإن Endianness لا يهم على الإطلاق لهذه القيم. العدد التالي من البايتات مطلوب لمجموعة معينة من القيم:

  • 1 بايت: من 0 إلى 127
  • 2 بايت: 128 إلى 16383
  • 3 بايت: 16،384 إلى 2،097،151
  • 4 بايت: 2،097،152 إلى 268،435،455
  • 5 بايت: 268،435،456 إلى 2،147،483،647 (Int32.MaxValue) و -2،147،483،648 (Int32.MinValue) إلى 1

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

وبالتالي ، لا أوصي به للقيم أو القيم السلبية أكبر من حوالي 250،000،000. لقد رأيته يستخدم داخليًا فقط لبادئة طول السلسلة من سلاسل .NET (تلك التي يمكنك قراءتها/الكتابة بها BinaryReader.ReadString و BinaryReader.WriteString) ، وصف عدد الأحرف التالية التي تتكون السلسلة ، فقط لها قيم إيجابية.

بينما يمكنك البحث عن المصدر الأصلي .NET, ، أستخدم تطبيقات مختلفة في بلدي مكتبة BinaryData.

اضطررت إلى استكشاف هذا التنسيق 7 بت أيضا. في أحد مشاريعي ، أقوم بتعبئة بعض البيانات في الملفات باستخدام C #'s BinaryWriter ثم قم بفكها مرة أخرى باستخدام BinaryReader ، الذي يعمل بشكل جيد.

في وقت لاحق ، كنت بحاجة إلى تنفيذ قارئ للملفات المليئة بهذا المشروع لـ Java أيضًا. لدى Java فئة تسمى DatainputStream (في حزمة Java.io) ، والتي لديها بعض الطرق المماثلة. لسوء الحظ ، يختلف تفسير بيانات DatainputStream تمامًا عن C#.

لحل مشكلتي ، قمت بنقل C #'s BinaryReader إلى Java بنفسي من خلال كتابة فصل يمتد Java.io.datainputStream. إليكم الطريقة التي كتبتها ، والتي تفعل تمامًا مثل C #'s BinaryReader.ReadString ():

public String csReadString() throws IOException {
    int stringLength = 0;
    boolean stringLengthParsed = false;
    int step = 0;
    while(!stringLengthParsed) {
        byte part = csReadByte();
        stringLengthParsed = (((int)part >> 7) == 0);
        int partCutter = part & 127;
        part = (byte)partCutter;
        int toAdd = (int)part << (step*7);
        stringLength += toAdd;
        step++;
    }
    char[] chars = new char[stringLength];
    for(int i = 0; i < stringLength; i++) {
        chars[i] = csReadChar();
    }
    return new String(chars);
}
/*
 * Parameters:  plOutput[out] - The decoded integer
 *              pbyInput[in]  - Buffer containing encoded integer
 * Returns:     Number of bytes used to encode the integer
 */
int SevenBitEncodingToInteger(int *plOutput, char *pbyInput)
{
    int lSize = 0;
    int lTemp = 0;
    while(true)
    {
        lTemp += pbyInput[lSize] & 0x7F;
        if(pbyInput[lSize++] > 127)
            lTemp <<= 7;
        else
            break;
    }
    *plOutput = lTemp;
    return lSize;
}

تحتوي طريقة Write7BitEncodedInt على الوصف: أدنى 7 بت من كل بايت تشفير 7 بتات التالية من الرقم. يتم تعيين أعلى بت عندما يكون هناك بايت آخر يتبع.

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