简体   繁体   中英

How can I read/write bits from/to a file in Java?

I need to read file stream as bits and then I should be able to write bits to file again. Are there any classes for this purpose?

As far as I know, there is no built in way to do it directly at the bit level. There are ways to read/write byte by byte using the built in streams. You could write a wrapper on a stream that looks like it reads and writes bits.

If you want something that is already written, look for open source projects that do certain kinds of audio or video encoding, since there are things like that. For instance, the FLAC codec had a BitInputStream that might meet your needs.

I was pretty happy with the colt library from CERN. Can't remember if it supports File I/O but I used it to read bitstreams, analyse and modify them and write them back to files.

Moved to https://github.com/jinahya/bit-io

Please take a look at 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>

This is a small handy library for reading/writing arbitrary length of bits with 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 might be what you are looking for. Looking at your questions, I could imagine that Preon might be even more than what you are looking for.

Think of Preon as a library that provides to bitstream encoded content what Hibernate aims to be to relational databases, and JAXB to XML. Now, it exists of a couple of modules. One of those modules is preon-binding. That's the actual data binding framework. (Driven by annotations.)

However, preon-binding is built on top of preon-bitbuffer (in later incarnations re-dubbed to preon-io). That library has BitBuffer type of abstraction for accessing bitstream compressed data.

alt text http://preon.flotsam.nl/images/layers.png

The Preon release last summer does not have support for encoding yet. That's work in progress.

And just to give you an idea of how to craft your own stream wrapper, here's the code snippet.

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

}

As you can see the read() method is overridden to return 0 or 1 if a bit is available, or -1 if the end of the underlying stream is reached.

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM