xxd -i
xxd -i
For large files, converting to text and then making the compiler parse it all over again is inefficient and unnecessary. Use objcopy instead:
objcopy -I binary -O elf32-i386 stuff stuff.o
(Adjust the output architecture as necessary for non-x86 platforms.) Then once you link it into your program, you can access it like so:
extern char _binary_stuff_start[], _binary_stuff_end[];
#define SIZE_OF_STUFF (_binary_stuff_end - _binary_stuff_start)
...
foo(_binary_stuff_start[i]);
1. print([hex(i) for in x])
2. print(a.hex())
Results will be:
1. ['0x61', '0x62', '0x63', '0x31', '0x32', '0x33']
2. '616263313233'
In case you want to use caps or not:
def bytes_to_c_arr(data, lowercase=True):
return [format(b, '#04x' if lowercase else '#04X') for b in data]
x = b'abc123'
print("unsigned char x[] = {{{}}}".format(", ".join(bytes_to_c_arr(x))))
print("unsigned char x[] = {{{}}}".format(", ".join(bytes_to_c_arr(x, False))))
# output: unsigned char x[] = {0x61, 0x62, 0x63, 0x31, 0x32, 0x33}
# unsigned char x[] = {0X61, 0X62, 0X63, 0X31, 0X32, 0X33}
xxd has a mode for this. The -i/--include option will:
output in C include file style. A complete static array definition is written (named after the input file), unless xxd reads from stdin.
You can dump that into a file to be #included, and then just access foo like any other character array (or link it in). It also includes a declaration of the length of the array.
The output is wrapped to 80 bytes and looks essentially like what you might write by hand:
$ xxd --include foo
unsigned char foo[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
0x21, 0x0a, 0x0a, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x76, 0x65,
0x72, 0x79, 0x20, 0x63, 0x75, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x21, 0x20,
0x57, 0x65, 0x6c, 0x6c, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x0a
};
unsigned int foo_len = 47;
xxd is, somewhat oddly, part of the vim distribution, so you likely have it already. If not, that's where you get it — you can also build the tool on its own out of the vim source.
You can almost do what you want with hexdump, but I can't figure out how to get quotes & single backslashes into the format string. So I do a little post-processing with sed. As a bonus, I've also indented each line by 4 spaces. :)
hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/.*/ "&"/'
Edit
As Cengiz Can pointed out, the above command line doesn't cope well with short data lines. So here's a new improved version:
hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x //g; s/.*/ "&"/'
As Malvineous mentions in the comments, we also need to pass the -v verbose option to hexdump to prevent it from abbreviating long runs of identical bytes to *.
hexdump -v -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x //g; s/.*/ "&"/'