Pergunta

Se você tem strings binárias (literalmente objetos String que contêm apenas 1 e 0), como você saída-los como bits em um arquivo?

Este é um compressor de texto que eu estava trabalhando; ele ainda está me incomodando, e que seria bom para finalmente fazê-lo funcionar. Obrigado!

Foi útil?

Solução

mais fácil é simplesmente ter 8 caracteres consecutivos, transformá-los em um byte e saída que byte. Pad com zeros no final, se você pode reconhecer o fim-de-stream, ou adicionar um cabeçalho com comprimento (em bits) no início do arquivo.

O loop interno seria algo parecido com:


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

Você vai precisar fazer alguns ajustes, mas essa é a idéia geral.

Outras dicas

Se você tiver sorte, java.math.BigInteger pode fazer tudo para você.

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

Esta não depende da ordem de bytes (big-endian) e-alinhamento direita (se o número de bits não é um múltiplo de 8) ser o que você quer, mas pode ser mais simples para modificar a matriz depois do que fazer o conversão de caracteres si mesmo.

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

E então ...

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

Assumindo que o String tem um múltiplo de oito bits, (você pode preenchê-lo de outra forma), tirar proveito de Java é construído em análise no método Integer.valueOf fazer algo parecido com isto:

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

Em seguida, você deve ser capaz de escrever os bytes para um FileOutputStream bastante simples.

Por outro lado, se você olhar para effeciency, você deve considerar não usando uma String para armazenar os bits para começar, mas construir os bytes diretamente em seu compressor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top