Embed Text File in a Resource in a native Windows Application

C++CWinapiResourcesText Files

C++ Problem Overview


I have a C++ Windows program. I have a text file that has some data. Currently, the text file is a separate file, and it is loaded at runtime and parsed. How is it possible to embed this into the binary as a resource?

C++ Solutions


Solution 1 - C++

Since you're working on a native Windows application, what you want to do is to create a user-defined resource to embed the contents of the text file into the compiled resource.

The format of a user-defined resource is documented on MSDN, as are the functions for loading it.

You embed your text file in a resource file like this:

nameID typeID filename

where nameID is some unique 16-bit unsigned integer that identifies the resource and typeID is some unique 16-bit unsigned integer greater than 255 that identifies the resource type (you may define those integers in the resource.h file). filename is the path to the file that you want to embed its binary contents into the compiled resource.

So you might have it like this:

In resource.h:

// Other defines...

#define TEXTFILE        256
#define IDR_MYTEXTFILE  101

In your resource file:

#include "resource.h"

// Other resource statements...

IDR_MYTEXTFILE TEXTFILE "mytextfile.txt"

Then you load it like this (error-checking code omitted for clarity):

#include <windows.h>
#include <cstdio>
#include "resource.h"

void LoadFileInResource(int name, int type, DWORD& size, const char*& data)
{
    HMODULE handle = ::GetModuleHandle(NULL);
    HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(name),
        MAKEINTRESOURCE(type));
    HGLOBAL rcData = ::LoadResource(handle, rc);
    size = ::SizeofResource(handle, rc);
    data = static_cast<const char*>(::LockResource(rcData));
}

// Usage example
int main()
{
    DWORD size = 0;
    const char* data = NULL;
    LoadFileInResource(IDR_MYTEXTFILE, TEXTFILE, size, data);
    /* Access bytes in data - here's a simple example involving text output*/
    // The text stored in the resource might not be NULL terminated.
    char* buffer = new char[size+1];
    ::memcpy(buffer, data, size);
    buffer[size] = 0; // NULL terminator
    ::printf("Contents of text file: %s\n", buffer); // Print as ASCII text
    delete[] buffer;
    return 0;
}

Note that you don't actually have to free the resource since the resource resides in the binary of the executable and the system will delete them automatically when the program exits (the function FreeResource() does nothing on 32-bit and 64-bit Windows systems).

Because the data resides in the executable binary, you can't modify it via the retrieved pointer directly (that's why the LoadFileInResource() function implementation stores the pointer in a const char*). You need to use the BeginUpdateResource(), UpdateResource(), and EndUpdateResource() functions to do that.

Solution 2 - C++

You can use xxd (from a linux machine or probably cygwin) to generate the data for a .h/.cc file.

There are lots of stack overflow questions that expand on this in detail:

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOliver ZhengView Question on Stackoverflow
Solution 1 - C++In silicoView Answer on Stackoverflow
Solution 2 - C++StephenView Answer on Stackoverflow