Lucky5
Lucky5

Reputation: 113

convert binary data into hex string for C program

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?

Upvotes: 2

Views: 13510

Answers (9)

Roland Puntaier
Roland Puntaier

Reputation: 3521

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))

Upvotes: 0

rustyx
rustyx

Reputation: 85530

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;

Upvotes: 8

Sascha Artamanov
Sascha Artamanov

Reputation: 11

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]);

Upvotes: 1

user821362
user821362

Reputation: 1

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;
            }
    }

    ....
}

Upvotes: 0

tristan_2468
tristan_2468

Reputation: 21

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

Upvotes: 0

Tanner
Tanner

Reputation: 630

#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

Upvotes: 2

z33m
z33m

Reputation: 6053

Upvotes: 0

Brian
Brian

Reputation: 25834

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)) + ",",

Upvotes: 1

Carl Norum
Carl Norum

Reputation: 225212

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

Upvotes: 0

Related Questions