Embed data in a C++ program

I've got a C++ program that uses SQLite. I want to store the SQL queries in a separate file -- a plain-text file, not a source code file -- but embed that file in the executable file like a resource.

(This has to run on Linux, so I can't store it as an actual resource as far as I know, though that would be perfect if it were for Windows.)

Is there any simple way to do it, or will it effectively require me to write my own resource system for Linux? (Easily possible, but it would take a lot longer.)


You can use objcopy to bind the contents of the file to a symbol your program can use. See, for instance, here for more information.


Use macros. Technically that file would be source code file but it wouldn't look like this. Example:

//queries.incl - SQL queries
Q(SELECT * FROM Users)
Q(INSERT [a] INTO Accounts)


//source.cpp
#define Q(query) #query,
char * queries[] = {
#include "queries.incl"
};
#undef Q

Later on you could do all sorts of other processing on that file by the same file, say you'd want to have array and a hash map of them, you could redefine Q to do another job and be done with it.


You can always write a small program or script to convert your text file into a header file and run it as part of your build process.


Here's a sample that we used for cross-platform embeddeding of files. It's pretty simplistic, but will probably work for you.

You may also need to change how it's handling linefeeds in the escapeLine function.

#include <string>
#include <iostream>
#include <fstream>
#include <cstdio>

using namespace std;

std::string escapeLine( std::string orig )
{
    string retme;
    for (unsigned int i=0; i<orig.size(); i++)
    {
        switch (orig[i])
        {
        case '\\':
            retme += "\\\\";
            break;
        case '"':
            retme += "\\\"";
            break;
        case '\n': // Strip out the final linefeed.
            break;
        default:
            retme += orig[i];
        }
    }
    retme += "\\n"; // Add an escaped linefeed to the escaped string.
    return retme;
}

int main( int argc, char ** argv )
{
    string filenamein, filenameout;

    if ( argc > 1 )
        filenamein = argv[ 1 ];
    else
    {
        // Not enough arguments
        fprintf( stderr, "Usage: %s <file to convert.mel> [ <output file name.mel> ]\n", argv[0] );
        exit( -1 );
    }

    if ( argc > 2 )
        filenameout = argv[ 2 ];
    else
    {
        string new_ending = "_mel.h";
        filenameout = filenamein;
        std::string::size_type pos;
        pos = filenameout.find( ".mel" );
        if (pos == std::string::npos)
            filenameout += new_ending;
        else
            filenameout.replace( pos, new_ending.size(), new_ending );
    }

    printf( "Converting \"%s\" to \"%s\"\n", filenamein.c_str(), filenameout.c_str() );

    ifstream filein( filenamein.c_str(), ios::in );
    ofstream fileout( filenameout.c_str(), ios::out );

    if (!filein.good())
    {
        fprintf( stderr, "Unable to open input file %s\n", filenamein.c_str() );
        exit( -2 );
    }
    if (!fileout.good())
    {
        fprintf( stderr, "Unable to open output file %s\n", filenameout.c_str() );
        exit( -3 );
    }

    // Write the file.
    fileout << "tempstr = ";

    while( filein.good() )
    {
        string buff;
        if ( getline( filein, buff ) )
        {
            fileout << "\"" << escapeLine( buff ) << "\"" << endl;
        }
    }

    fileout << ";" << endl;

    filein.close();
    fileout.close();

    return 0;
}