سؤال

إذا كان لديك سلاسل ثنائية (حرفيًا كائنات سلسلة تحتوي على 1 و0 فقط)، فكيف يمكنك إخراجها كبتات في ملف؟

هذا خاص بضاغط النص الذي كنت أعمل عليه؛لا يزال الأمر يزعجني، وسيكون من الجيد أن أتمكن من تشغيله أخيرًا.شكرًا!

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

المحلول

الأسهل هو ببساطة أخذ 8 أحرف متتالية وتحويلها إلى بايت وإخراج تلك البايت.ضع أصفارًا في النهاية إذا كان بإمكانك التعرف على نهاية الدفق، أو أضف رأسًا بطول (بالبت) في بداية الملف.

ستبدو الحلقة الداخلية كما يلي:


byte[] buffer = new byte[ ( string.length + 7 ) / 8 ];
for ( int i = 0; i < buffer.length; ++i ) {
   byte current = 0;
   for ( int j = 7; j >= 0; --j )
       if ( string[ i * 8 + j ] == '1' )
           current |= 1 << j;
   output( current );
}

سوف تحتاج إلى إجراء بعض التعديلات، ولكن هذه هي الفكرة العامة.

نصائح أخرى

إذا كنت محظوظًا، فقد يقوم java.math.BigInteger بكل شيء من أجلك.

String s = "11001010001010101110101001001110";
byte[] bytes = (new java.math.BigInteger(s, 2)).toByteArray();

يعتمد هذا على ترتيب البايت (النهاية الكبيرة) والمحاذاة لليمين (إذا لم يكن عدد البتات من مضاعفات 8) وهو ما تريده ولكن قد يكون تعديل المصفوفة بعد ذلك أسهل من إجراء تحويل الأحرف بنفسك .

public class BitOutputStream extends FilterOutputStream
{
    private int buffer   = 0;
    private int bitCount = 0;

    public BitOutputStream(OutputStream out)
    {
        super(out);
    }

    public void writeBits(int value, int numBits) throws IOException
    {
        while(numBits>0)
        {
            numBits--;
            int mix = ((value&1)<<bitCount++);
            buffer|=mix;
            value>>=1;
            if(bitCount==8)
                align8();
        }
    }

    @Override
    public void close() throws IOException
    {
        align8(); /* Flush any remaining partial bytes */
        super.close();
    }

    public void align8() throws IOException
    {
        if(bitCount > 0)
        {
            bitCount=0;
            write(buffer);
            buffer=0;
        }
    }
}

وثم...

if (nextChar == '0')
{
    bos.writeBits(0, 1);
}
else
{
    bos.writeBits(1, 1);
}

بافتراض أن السلسلة تحتوي على مضاعفات ثمانية بتات، (يمكنك إضافتها بطريقة أخرى)، استفد من التحليل المدمج في Java في طريقة Integer.valueOf للقيام بشيء مثل هذا:

String s = "11001010001010101110101001001110";
byte[] data = new byte[s.length() / 8];
for (int i = 0; i < data.length; i++) {
    data[i] = (byte) Integer.parseInt(s.substring(i * 8, (i + 1) * 8), 2);
}

ثم يجب أن تكون قادرًا على كتابة البايتات إلى ملف FileOutputStream بكل بساطة.

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

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