How to dump a binary file as a C/C++ string literal?
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 #include
d, 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/.*/ "&"/'
xxd
is good but the result is highly verbose and takes a lot of storage space.
You can achieve practically the same thing using objcopy
; e.g.
objcopy --input binary \
--output elf32-i386 \
--binary-architecture i386 foo foo.o
Then link foo.o
to your program and simply use the following symbols:
00000550 D _binary_foo_end
00000550 A _binary_foo_size
00000000 D _binary_foo_start
This is not a string literal, but it's essentially the same thing as what a string literal turns into during compilation (consider that string literals do not in fact exist at run-time; indeed, none of the other answers actually give you a string literal even at compile-time) and can be accessed in largely the same way:
unsigned char* ptr = _binary_foo_start;
int i;
for (i = 0; i < _binary_foo_size; i++, ptr++)
putc(*ptr);
The downside is that you need to specify your target architecture to make the object file compatible, and this may not be trivial in your build system.