Reputation: 113
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
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
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
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
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
Reputation: 21
The open source application Hexy is designed specifically for this. It runs on Windows and Linux.
Upvotes: 0
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
Reputation: 6053
Upvotes: 0
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
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