Mark green
Mark green

Reputation: 43

How to write single bits into bin file

i am trying to make an compress program that for example write instead regular 8 bits (char) only 1 or 2 bits, depend of the char we are trying to write. i tried to write with:

//I dont know what the function should return
char getBytes(char c)
{
    return 0xff;
}

ofstream fout;
fout.open("file.bin", ios::binary | ios::out);
fout << getBytes(c); 

but so far i succed writing only chars. so how can i write for example: '01'? or only '1'? in what function i should use for write into file with only bytes? thanks.

Upvotes: 0

Views: 136

Answers (1)

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153792

Streams are sequences of bytes. There is no standard interface to write individual bits. If you want to write individual bits you’ll need to create your own abstraction of a bit stream built on top of streams. It would aggregate multiple bits into a byte which is then written to the underlying stream. If you want reasonable efficient writing you’ll probably need to aggregate multiple bytes before writing them to the stream.

A naïve implementation could look something like this:

class bitstream {
    std::streambuf* sbuf;
    int             count = 0;
    unsigned char   byte = 0;
public:
    bitstream(std::ostream& out): sbuf(out.rdbuf()) {}
    ~bitstream() {
        if (this->count) {
            this->sbuf->sputc(this->byte);
        }
    }
    bitstream& operator<< (bool b) {
        this->byte = (this->byte << 1) | b;
        if (++this->count == 8) {
            this->sbuf->sputc(this->byte);
            this->count = 0;
        }
        return *this;
    }
};

Note that this implementation has rather basic handling for the last byte: if a byte was started it will be written as is. Whether that is the intended behavior or whether it needs to be shifted for the written bits being in the top bits of the last byte depends on how things are being used. Also, there is no error handling for the case that the underlying stream couldn’t be written. (and the code is untest - I don’t have an easy way to compile on my mobile phone)

You’d use the class something like this:

int main() {
    std::ofstream file(“bits.txt”, std::ios_base::binary);
    bitstream       out(file);

    out << false << true << false << false
        << false << false << false << true;
}

Unless I messed things up, the above code should write A into the file bits.txt (the ASCII code for A is 65).

Just for context: files are actually organized into blocks of bytes. However, the stream abstraction aggregates the individual bytes written into blocks. Although byte oriented interfaces are provided by all popular operating systems writing anything but blocks of data tends to be rather inefficient.

Upvotes: 1

Related Questions