2

I have a small binary image, that needs to be represented in a C program. The representation will be like:

static const char[] = {0x1, 0x2, 0x3, 0x4...};

(so, the bytes will be represented as a series of chars)

How do I convert a binary file into a nice 0x..,0x.. string? Is there a program to do this?

Lucky5
  • 113
  • 1
  • 2
  • 4

9 Answers9

8

Use the xxd utility:

$ xxd -i binary.bin > binary.c

Will create binary.c with the following content:

unsigned char binary_bin[] = {
  0x01, 0x02, 0x03, 0x04,   . . .
  . . .
};
unsigned int binary_bin_len = 123456;
rustyx
  • 80,671
  • 25
  • 200
  • 267
2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH 80

int main(void)
{
    FILE *fout = fopen("out.txt", "w");

    if(ferror(fout))
    {
        fprintf(stderr, "Error opening output file");
        return 1;
    }
    char init_line[]  = {"char hex_array[] = { "};
    const int offset_length = strlen(init_line);

    char offset_spc[offset_length];

    unsigned char buff[1024];
    char curr_out[64];

    int count, i;
    int line_length = 0;

    memset((void*)offset_spc, (char)32, sizeof(char) * offset_length - 1);
    offset_spc[offset_length - 1] = '\0';

    fprintf(fout, "%s", init_line);

    while(!feof(stdin))
    {
        count = fread(buff, sizeof(char), sizeof(buff) / sizeof(char), stdin);

        for(i = 0; i < count; i++)
        {
            line_length += sprintf(curr_out, "%#x, ", buff[i]);

            fprintf(fout, "%s", curr_out);
            if(line_length >= MAX_LENGTH - offset_length)
            {
                fprintf(fout, "\n%s", offset_spc);
                line_length = 0;
            }
        }
    }
    fseek(fout, -2, SEEK_CUR);
    fprintf(fout, " };");

    fclose(fout);

    return EXIT_SUCCESS;
}

Here, updated, works. Pipe in the file, it spits it out as an unsigned char array in hex to out.txt.

Another edit: Figured I might as well make it nice. Prints it out to out.txt, an unsigned char array and nicely formatted. Should be trivial from here if you want to add anything to it

Tanner
  • 630
  • 1
  • 7
  • 20
1

If pBuff is your binary data, try to figure out the length of your buffer, e.g.

lenBuffer= sizeof(..);
for (i = 0; i < lenBuffer; i++)
  printf("%x ", pBuff[i]);
Mateusz
  • 3,038
  • 4
  • 27
  • 41
1

In Python 2.6

from __future__ import with_statement
with open('myfile.bin') as f:
    s = f.read()
    for c in s:
        print hex(ord(c)) + ",",
Brian
  • 25,523
  • 18
  • 82
  • 173
0

You can write a program to do it pretty easily, but here is a perl script that can do it for you.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
0
z33m
  • 5,993
  • 1
  • 31
  • 42
0

The open source application Hexy is designed specifically for this. It runs on Windows and Linux.

0

Works great! However I made a small change to allow for the input and output files to be specified on the command line:

int main(int argc, char **argv)
{
    FILE *fout = NULL;
    FILE *fin = NULL;
    const char *optstring = "i:o";
    char ch;
    int argind = 1;

    if(argc < 5)
    {
            fprintf(stderr,"Usage: bin2array -i <input_file> -o <output_file>\n");
            return 2;
    }

    while((ch = getopt(argc,argv,optstring)) != -1)
    {
            switch(ch)
            {
            case 'i':
                    argind++;
                    fprintf(stderr,"File: %s\n",argv[argind]);
                    fin = fopen(argv[argind],"rb");
                    argind++;
                    break;
            case 'o':
                    argind++;
                    fprintf(stderr,"File: %s\n",argv[argind]);
                    fout = fopen(argv[argind],"wt");
                    argind++;
                    break;
            }
    }

    ....
}
chris
  • 36,115
  • 52
  • 143
  • 252
0

This Python code/script produces a C/C++ string of a binary blob. Octal escapes makes the string shorter than hex escapes.

#!/usr/bin/env python3

"""
:c_str_literal():
produces `"<ascii with special C escapes and oct escapes else>"` from a python `bytes` object.

The whole file converts a binary file into a file
containing the string produced by c_str_literal().

#Test
python -c 'with open("/tmp/test_bin2c_py.dat","bw") as f: f.write(bytes(range(256)))'
python ./bin2c.py /tmp/test_bin2c_py.dat
cat << EOF > /tmp/test_bin2c_py.cpp
#include <cassert>
unsigned char data[] = 
#include "test_bin2c_py.dat.inc"
;
// sizeof(data) includes a terminating 0
int main() {assert(data[0]==0 && data[sizeof(data)-2]==255);}
EOF
g++ /tmp/test_bin2c_py.cpp -std=c++17 -o /tmp/test_bin2c_py && /tmp/test_bin2c_py
rm /tmp/test_bin2c_py.dat.inc
rm /tmp/test_bin2c_py.cpp
cat /tmp/test_bin2c_py.dat | python ./bin2c.py
rm /tmp/test_bin2c_py.dat
"""

import sys

c_str_literal = lambda d: '"{}"'.format(''.join(bytes_to_c_ascii_oct(d)))
def bytes_to_c_ascii_oct(d):
   """Convert binary data to C/C++ ASCII encoding.
   >>> d=bytes([0,ord('0'),3,ord('9'),ord(' '),ord('\t'),13])
   >>> c_str_literal(d)
   '"\\0000\\39 \\t\\r"'
   >>> d=bytes(range(256))
   >>> c_str_literal(d)[:9]
   '"\\0\\1\\2\\3'
   >>> c_str_literal(d)[-9:]
   '\\376\\377"'
   >>> d=bytes([92,56])
   >>> c_str_literal(d)
   '"\\\\8"'
   >>> d=b'\a\b\f\r\t\v\'\"\n'
   >>> c_str_literal(d)
   '"\\7\\b\\f\\r\\t\\v\'\\"\\n"'
   >>> d=bytes([63,63,ord('<')])
   >>> c_str_literal(d)
   '"\\?\\?<"'
   >>> from base64 import b64decode as b64d
   >>> d=b64d("2y1+2oAR6w8dzIYARovDfz/PD7JA8NW/fEteMTPNmpK7oswK8wWwR1ZMgH8//9Q74xRdcIWfPk8nr/9Pq9xQGDFv")
   >>> c_str_literal(d)[-8:]
   'P\\0301o"'

   """
   b2enc = ['\\0', '\\1', '\\2', '\\3', '\\4', '\\5', '\\6', '\\7', '\\b', '\\t', '\\n',
      '\\v', '\\f', '\\r', '\\16', '\\17', '\\20', '\\21', '\\22', '\\23', '\\24',
      '\\25', '\\26', '\\27', '\\30', '\\31', '\\32', '\\33', '\\34', '\\35', '\\36',
      '\\37', ' ', '!', '\\"', '#', '$', '%', '&', "'", '(', ')', '*', '+',
      ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':',
      ';', '<', '=', '>', '\\?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
      'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
      'Z', '[', '\\\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
      'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
      'y', 'z', '{', '|', '}', '~', '\\177', '\\200', '\\201', '\\202', '\\203', '\\204',
      '\\205', '\\206', '\\207', '\\210', '\\211', '\\212', '\\213', '\\214', '\\215', '\\216',
      '\\217', '\\220', '\\221', '\\222', '\\223', '\\224', '\\225', '\\226', '\\227', '\\230',
      '\\231', '\\232', '\\233', '\\234', '\\235', '\\236', '\\237', '\\240', '\\241', '\\242',
      '\\243', '\\244', '\\245', '\\246', '\\247', '\\250', '\\251', '\\252', '\\253', '\\254',
      '\\255', '\\256', '\\257', '\\260', '\\261', '\\262', '\\263', '\\264', '\\265', '\\266',
      '\\267', '\\270', '\\271', '\\272', '\\273', '\\274', '\\275', '\\276', '\\277', '\\300',
      '\\301', '\\302', '\\303', '\\304', '\\305', '\\306', '\\307', '\\310', '\\311', '\\312',
      '\\313', '\\314', '\\315', '\\316', '\\317', '\\320', '\\321', '\\322', '\\323', '\\324',
      '\\325', '\\326', '\\327', '\\330', '\\331', '\\332', '\\333', '\\334', '\\335', '\\336',
      '\\337', '\\340', '\\341', '\\342', '\\343', '\\344', '\\345', '\\346', '\\347', '\\350',
      '\\351', '\\352', '\\353', '\\354', '\\355', '\\356', '\\357', '\\360', '\\361', '\\362',
      '\\363', '\\364', '\\365', '\\366', '\\367', '\\370', '\\371', '\\372', '\\373', '\\374',
      '\\375', '\\376', '\\377']
   ord0,ord7,o16 = ord('0'),ord('7'),14
   lend = len(d)
   i,j = 0,1
   while j <= lend:
       di = d[i]
       bi = b2enc[di]
       if j == lend:
           yield bi
           break
       dj = d[j]
       if ((di<=7 or (di>=o16 and di<32))
           and dj>=ord0 and dj<=ord7):
           yield '\\'+"{:0>3o}".format(di)
       else:
           yield bi
       i,j = i+1,j+1

if __name__ == '__main__':
   a = sys.argv
   if len(a) > 2 or len(a)==2 and (a[1]=='--help' or a[1]=='-h'):
       print("{} [<filename>|--help|-h]".format(a[0]))
       print("stdin/stdout if no file name is given, else '.inc' is appended")
       exit(0)
   fi = len(a)==2 and open(a[1],'br') or sys.stdin.buffer
   fo = len(a)==2 and open(a[1]+'.inc','w') or sys.stdout
   d = fi.read()
   fo.write(c_str_literal(d))
Roland Puntaier
  • 3,250
  • 30
  • 35