0

How can I read a binary file (I don't know its type or what is stored in it) and print out the 0s and 1s into a text file?

#include <iostream>
#include <fstream>
#include <string.h>
#include <iomanip>


using namespace std;


int main(int argc, char *argv[])
{
    char ch;
    bool x;
    int i = 0;

    if (argc < 3)
    {
        cout << endl << "Please put in all parameters" << endl;
        return 0;
    }

    char *c = new char[4];

    ifstream fin(argv[1], ios_base::in | ios_base::binary);

    if (!fin.is_open())
    {
        cout << "Error opening input file" << endl;
        return 0;
    }

    if (!strcmp(argv[2], "-file"))
    {
        ofstream fout(argv[3]);

        if (!fout.is_open())
        {
            cout << "Error opening output file" << endl;
            return 0;
        }

        while (fin.read(c, sizeof ch))
        {
            fout << c;
        }

        cout << "Contents written to file successfully" << endl;
        fout.close();
    }
    else if (!strcmp(argv[2], "-screen"))
    {

        cout << endl << "Contents of the file: " << endl;

        while (fin.read((char *)&x,sizeof x))
        {
            cout << x;
        }

        cout << endl;
    }
    else
    {
        cout << endl << "Please input correct option" << endl;
        return 0;
    }

    fin.close();
    return 0;
}
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Jonna
  • 141
  • 1
  • 4

4 Answers4

0

Yes, just use fstreams and open the file with the binary flag, then you can handle the resource like a normal fstream and stream it into a text file. If you want to convert the 0 and 1 to chars it will get a bit more complicated. The easiest way for that will most likely be to buffer the bytes in unsigned chars like here and then try to manipulate those via sprintf.

fstream API

sprintf API

Community
  • 1
  • 1
Sim
  • 4,199
  • 4
  • 39
  • 77
  • @quasiverse: Tell you what, `sprintf` rocks in both C and C++. –  Sep 21 '11 at 23:58
  • @Vlad, c is subset of c++ which make that statement true. however, if people misunderstood printf as c++ operations and proceed with them instead of stream-based operation, they might miss any future improvement on the latter. – YeenFei Sep 22 '11 at 00:53
0

For better or worse, I find this easiest done with printf:

#include <fstream>
#include <cstdio>

static const std::size_t blocks = 256;
char buf[blocks * 16];

std::ifstream infile(filename, "rb");

do
{
  infile.read(buf, blocks * 16);

  for (std::size_t i = 0; i * 16 < infile.gcount(); ++i)
  {
    for (std::size_t j = 0; j < 16 && 16 * i + j < infile.gcount(); ++j)
    {
      if (j != 0) std::printf(" ");
      std::printf("0x%02X", static_cast<unsigned char>(buf[16 * i + j]));
    }
  }
} while (infile);

I chose an arbitrary line length of 16 bytes per line for this, and I'm reading 4kiB at a time -- this can be tuned for maximum efficiency. It's important to use gcount() to get the actual number of read bytes, since the last round of the loop may read less than 4kiB.

Note that this is essentially equivalent to the hexdump utility.

If you wanted acutal binary output, you could just write a little helper routine for that in place of the printf.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

As I got, you don't need hexadecimal output but binary (0s and 1s), despite of the fact I don't understand why. There's no io manipulator to output binary data. You need to do this yourself using bitwise operators. Something like this:

char c; // contains byte read from input
for (size_t i = 0; i != sizeof(c); ++i) {
    std::cout << c & 0x80; // grab most significant bit
    c <<= 1; // right shift by 1 bit
} 
Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
0

The easiest way is probably to create an std::bitset from the inputs, and print them out. Ignoring error checking and such, a simple version would come out something like this:

#include <bitset>
#include <fstream>
#include <iostream>
#include <ios>
#include <iomanip>

int main(int argc, char **argv) { 
    std::ifstream infile(argv[1], std::ios::binary);
    char ch;
    unsigned long count = 0;

    while (infile.read(&ch, 1)) {
        if (count++ % 4 == 0)
            std::cout << "\n" << std::setw(6) << std::hex << count;
        std::cout << std::setw(10) << std::bitset<8>(ch);
    }   
    return 0;
}

I'd consider the normal dump in hexadecimal a lot more usable though. I'm only displaying four bytes per line above (8 would fit in 80 columns only by omitting the offset at the beginning of the line, which would be a serious loss, at least in my experience), so an entire screen will typically be only ~200 bytes or so. In hexadecimal, you can (and usually do) display 16 bytes per line, in both hex and (for printable characters) as themselves as well.

I should add, however, that I've been using hex dumps for decades now, so my opinion could be based at least partly on bias rather than real facts.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111