Search code examples
javafilefileoutputstreambitset

Writing Bits to a file using BitSet & FileOutputStream


I've run into a bit of a problem when it comes to writing specific bits to a file. I apologise if this is a duplicate of anything but I could not find a reasonable answer with the searches I ran.

I have a number of difficulties with the following:

  1. Writing a header (Long) bit by bit (converted to a byte array so the FileOutputStream can utilise it) to the file.

  2. Writing single bits to the file. For example, at one stage I am required to write a single bit set to 0 to the file so my initial thought would be to use a BitSet but Java seems to treat this as a null?

    BitSet initialPadding = new BitSet();
    initialPadding.set(0, false);
    fileOutputStream.write(initialPadding.toByteArray());
    

1)

I create a FileOutputStream as shown below with the necessary file name:

FileOutputStream fileOutputStream = new FileOutputStream(file.getAbsolutePath());

I am attempting to create an ".amr" file so the first step before I perform any bit manipulation is to write a header to the beginning of the file. This has the following value:

Long defaultHeader = 0x2321414d520aL;

I've tried writing this to the file using the following method but I am pretty sure it does not write the correct result:

fileOutputStream.write(defaultHeader.byteValue()); 

Am I using the correct streams? Are my convertions completely wrong?


2)

I have a public BitSet fileBitSet;which has bits read in from a ".raw" file as the input. I need to be able to extract certain bits from the BitSet in order to write them to the file later. I do this using the following method:

public int getOctetPayloadHeader(int startPoint) {

    int readLength = 0;

    octetCMR = fileBitSet.get(0, 3);
    octetRES = fileBitSet.get(4, 7);

    if (octetRES.get(0, 3).isEmpty()) {

        /* Keep constructing the payload header. */

        octetFBit    = fileBitSet.get(8, 8);
        octetMode    = fileBitSet.get(9, 12);
        octetQuality = fileBitSet.get(13, 13);
        octetPadding = fileBitSet.get(14, 15);
        ... }

What would be the best way to go for writing these bits to a file bearing in mind that I may be required to sometimes write a single bit or 81 bits at a particular offset in the fileBitSet ?


Solution

  • There is only one thing you can write to an OutputStream: bytes. You have to do the composing of your bits into bytes yourself; only you know the rules how the bits are to be put together into bytes.

    As for stuff like:

    Long defaultHeader = 0x2321414d520aL;
    fileOutputStream.write(defaultHeader.byteValue()); 
    

    You should take a close look at the javadocs for the methods you are using. byteValue() returns a single byte; so of course its not doing what you expect. Working with streams is well explained in oracles tutorials: http://docs.oracle.com/javase/tutorial/essential/io/streams.html

    For writing single bits or groups of bits, you will need a custom OutputStream that handles grouping the bits into bytes to be written. Thats commonly called a BitStream (there is no such class in the JDK); you have to either write it yourself (which I highly recommend, its a very good excercise to teach you about bits and bytes) or find one on the web.