"#include" a text file in a C program as a char[]
Is there a way to include an entire text file as a string in a C program at compile-time?
something like:
-
file.txt:
This is a little text file
-
main.c:
#include <stdio.h> int main(void) { #blackmagicinclude("file.txt", content) /* equiv: char[] content = "This is\na little\ntext file"; */ printf("%s", content); }
obtaining a little program that prints on stdout "This is a little text file"
At the moment I used an hackish python script, but it's butt-ugly and limited to only one variable name, can you tell me another way to do it?
I'd suggest using (unix util)xxd for this. you can use it like so
$ echo hello world > a
$ xxd -i a
outputs:
unsigned char a[] = {
0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a
};
unsigned int a_len = 12;
The question was about C but in case someone tries to do it with C++11 then it can be done with only little changes to the included text file thanks to the new raw string literals:
In C++ do this:
const char *s =
#include "test.txt"
;
In the text file do this:
R"(Line 1
Line 2
Line 3
Line 4
Line 5
Line 6)"
So there must only be a prefix at the top of the file and a suffix at the end of it. Between it you can do what you want, no special escaping is necessary as long as you don't need the character sequence )"
. But even this can work if you specify your own custom delimiter:
R"=====(Line 1
Line 2
Line 3
Now you can use "( and )" in the text file, too.
Line 5
Line 6)====="
I like kayahr's answer. If you don't want to touch the input files however, and if you are using CMake, you can add the delimeter character sequences on the file. The following CMake code, for instance, copies the input files and wraps their content accordingly:
function(make_includable input_file output_file)
file(READ ${input_file} content)
set(delim "for_c++_include")
set(content "R\"${delim}(\n${content})${delim}\"")
file(WRITE ${output_file} "${content}")
endfunction(make_includable)
# Use like
make_includable(external/shaders/cool.frag generated/cool.frag)
Then include in c++ like this:
constexpr char *test =
#include "generated/cool.frag"
;