Битовые манипуляции и вывод в Java - PullRequest
5 голосов
/ 18 сентября 2008

Если у вас есть двоичные строки (буквально объекты String, которые содержат только 1 и 0), как бы вы вывели их в виде битов в файл?

Это для текстового компрессора, над которым я работал; это все еще беспокоит меня, и было бы неплохо, наконец, заставить его работать. Спасибо!

Ответы [ 4 ]

6 голосов
/ 18 сентября 2008

Если вам повезет, java.math.BigInteger может сделать все для вас.

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

Это зависит от порядка байтов (big-endian) и выравнивания по правому краю (если число битов не кратно 8), что вам нужно, но впоследствии может быть проще изменить массив, чем сделать преобразование персонажа самостоятельно.

6 голосов
/ 18 сентября 2008

Проще всего взять 8 последовательных символов, превратить их в байт и вывести этот байт. Дополните нулями конец, если вы можете распознать конец потока, или добавьте заголовок с длиной (в битах) в начале файла.

Внутренний цикл будет выглядеть примерно так:

<code>
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 );
}

Вам нужно будет внести некоторые коррективы, но это общая идея.

2 голосов
/ 18 сентября 2008
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);
}
1 голос
/ 18 сентября 2008

Предполагая, что String имеет кратное восьми бит (вы можете добавить его в противном случае), воспользуйтесь встроенным синтаксическим анализом 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 довольно просто.

С другой стороны, если вы ищете эффективность, вам следует подумать не об использовании строки для хранения битов, а о создании байтов непосредственно в вашем компрессоре.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...