Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing binary files in C++

Tags:

c++

binary

I have a device which sends me binary data of type uint32_t. I want to save the data to a binary file. Here is my code:

#include<iostream>
#include<fstream>
#include <cstdlib>

using namespace std;

int main()
{
   ofstream myFile ("data2.bin", ios::out | ios::binary);

   bool buffer[32];

   for (int k = 0; k<100; k++)
   {
      for (int i = 0; i<32;i++) 
   {
     buffer[i] = (bool)rand()%2;
   }
   myFile.write ((char*)&buffer, 32);
  }
   myFile.close();
}

It works, but the size of the file is 3.2 kB, not 0.4 kB. Moreover, when I try to read the data from the file (the data produced by my device), I get strange outcome, not in the format described in the manual. Of course, there is more data than I expect.

What am I doing wrong?

like image 635
user2738748 Avatar asked Apr 20 '15 19:04

user2738748


1 Answers

A bool takes one byte. Check sizeof(bool) and you'll find it equal to 1. So the array is 32 bytes long and you're writing it 100 times, therefore 3.2kB.

If you want to store a bit array, you need to use something different from an array of bool. You have a number of options:

  1. Use an array of bytes, integers, or anything whose size you know, and explicitly turn on the bits that you want. Then, store the array.

    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <cstdint>
    
    using namespace std;
    
    int main()
    {
      ofstream myFile ("data2.bin", ios::out | ios::binary);
    
      uint32_t buffer;
    
      for (int k = 0; k<100; k++) {
        buffer = 0;
        for (int i = 0; i<32; i++) {
          buffer <<= 1;
          buffer |= (bool)(rand()%2);
        }
        myFile.write((char*) &buffer, sizeof(buffer));
      }
      myFile.close();
      return 0;
    }
    

    In fact, if you already have an array of uint32_t to begin with, then you don't need the loop and you can just store the array directly. Use the exact myFile.write line above, where buffer is your uint32_t array.

  2. Use a vector<bool> or preferably a bitset. Both are optimized and use one bit per element.

    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <bitset>
    
    using namespace std;
    
    int main()
    {
      ofstream myFile ("data2.bin", ios::out | ios::binary);
    
      bitset<32> buffer;
    
      for (int k = 0; k<100; k++) {
        for (int i = 0; i<32; i++) {
          buffer[i] = (bool)(rand()%2);
        }
        myFile.write((char*) &buffer, 32/8);
      }
      myFile.close();
      return 0;
    }
    

Of course, in both cases, you output bytes to your file. In the second case, the number of bits has to be a multiple of 8.

like image 91
nickie Avatar answered Nov 10 '22 12:11

nickie