Embed Text File in a Resource in a native Windows Application

31,453

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.

Share:
31,453
Oliver Zheng
Author by

Oliver Zheng

Updated on March 16, 2020

Comments

  • Oliver Zheng
    Oliver Zheng about 4 years

    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?

  • IInspectable
    IInspectable about 10 years
    -1 PE(+) files are already capable of storing custom resources, and the Windows build tools have everything you need. The resource script syntax is documented, and the OS provides APIs for accessing that data. This answer is the answer to another question.
  • utvecklare
    utvecklare about 8 years
    I have one more general wondering asked here. Could you please answer to my second question that is related to your answer? Just how to have a dll file that has a function to contain the code that is in main in your answer.
  • Raindrop7
    Raindrop7 over 6 years
    " the system will delete them automatically when the program exits" Don't all program when exit the system free resources? Memory leak and resource leak occurs during the execution of an executable. So if this program loads n of the same resource it will issue in a resource leak.
  • Laurie Stearn
    Laurie Stearn about 6 years
    In the properties of the resource file there's "Null Terminate Strings"
  • Programmer
    Programmer over 5 years
    I have a win32 application. Can I know where I can find the resource file and how I can create a user-defined resource file? I want to load an xml file during the build itself. File size is 20MB.