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?
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:
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.
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.