Как я могу читать/писать биты из/в файл в Java?

Мне нужно прочитать поток файлов как биты, а затем я должен иметь возможность писать биты в файл снова. Существуют ли какие-либо классы для этой цели?

5 ответов


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

Если вы хотите что-то, что уже написано, ищите проекты с открытым исходным кодом, что у некоторых видов аудио и видео кодирования, так как есть такие вещи. Например, кодек FLAC имел BitInputStream, который может удовлетворить ваши потребности.


Я был очень доволен Кольт библиотека из ЦЕРНа. Не помню, поддерживает ли он файловый ввод-вывод, но я использовал его для чтения bitstreams, анализа и изменения их и записи в файлы.


переехал в https://github.com/jinahya/bit-io

пожалуйста, взгляните на http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/bit-io/src/main/java/com/googlecode/jinahya/io/

<dependency>
  <!-- resides in central repo -->
  <groupId>com.googlecode.jinahya</groupId>
  <artifactId>bit-io</artifactId>
  <version>1.0-alpha-13</version>
</dependency>

Это небольшая удобная библиотека для чтения/записи произвольной длины битов с Java.

final InputStream stream;
final BitInput input = new BitInput(new BitInput.StreamInput(stream));

final int b = input.readBoolean(); // reads a 1-bit boolean value
final int i = input.readUnsignedInt(3); // reads a 3-bit unsigned int
final long l = input.readLong(47); // reads a 47-bit signed long

input.align(1); // 8-bit byte align; padding


final WritableByteChannel channel;
final BitOutput output = new BitOutput(new BitOutput.ChannelOutput(channel));

output.writeBoolean(true); // writes a 1-bit boolean value
output.writeInt(17, 0x00); // writes a 17-bit signed int
output.writeUnsignedLong(54, 0x00L); // writes a 54-bit unsigned long

output.align(4); // 32-bit byte align; discarding

Преон может быть то, что вы ищете. Глядя на ваши вопросы, я могу себе представить, что Преон может быть даже больше чем то, что вы ищете.

подумайте о Preon как о библиотеке, которая предоставляет битовому кодированному контенту то, что Hibernate стремится быть реляционными базами данных, а JAXB-XML. Сейчас существует пару модулей. Один из этих модулей-preon-binding. Это фактическая структура привязки данных. (Движимый комментарии.)

однако preon-binding построен поверх preon-bitbuffer (в более поздних воплощениях переименован в preon-io). Эта библиотека имеет тип абстракции BitBuffer для доступа к сжатым данным bitstream.

alt текст http://preon.flotsam.nl/images/layers.png

выпуск Preon прошлым летом еще не имеет поддержки для кодирования. Это работа в процессе.


и просто чтобы дать вам представление о том, как создать свою собственную обертку потока, вот фрагмент кода.

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

public class BitInputStream extends FilterInputStream {

    private int bitsBuffer = -1;

    private int remainingBits = 0;

    public BitInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        if (remainingBits == 0) {
            bitsBuffer = in.read();
            remainingBits = Byte.SIZE;
        }
        if (bitsBuffer == -1) {
            return -1;
        }
        remainingBits--;
        return (bitsBuffer >> remainingBits) & 1;
    }

}

Как вы можете видеть, метод read () переопределяется для возврата 0 или 1, если бит доступен, или -1, если достигнут конец базового потока.

import org.junit.Test;
import java.io.ByteArrayInputStream;
import static org.junit.Assert.assertEquals;

public class BitInputStreamTest {

    @Test
    public void read() throws Exception {
        // 99 in two's complement binary form is 01100011
        BitInputStream in = new BitInputStream(
          new ByteArrayInputStream(new byte[]{99}));

        assertEquals(0, in.read());
        assertEquals(1, in.read());
        assertEquals(1, in.read());
        assertEquals(0, in.read());

        assertEquals(0, in.read());
        assertEquals(0, in.read());
        assertEquals(1, in.read());
        assertEquals(1, in.read());

        assertEquals(-1, in.read());
    }

}