【问题标题】:Embed Text File in a Resource in a native Windows Application在本机 Windows 应用程序的资源中嵌入文本文件
【发布时间】:2011-02-25 08:56:52
【问题描述】:

我有一个 C++ Windows 程序。我有一个包含一些数据的文本文件。目前,文本文件是一个单独的文件,在运行时加载并解析。如何将它作为资源嵌入到二进制文件中?

【问题讨论】:

    标签: c++ c winapi resources text-files


    【解决方案1】:

    由于您正在开发本机 Windows 应用程序,因此您要做的是创建一个用户定义的资源,以将文本文件的内容嵌入到已编译的资源中。

    用户定义资源的格式是documented on MSDNthe functions for loading it也是。

    您将文本文件嵌入到这样的资源文件中:

    nameID typeID filename
    

    其中nameID 是标识资源的唯一16 位无符号整数,typeID 是标识资源类型的大于255 的唯一16 位无符号整数(您可以在resource.h 中定义这些整数文件)。 filename 是您要将其二进制内容嵌入到已编译资源中的文件的路径。

    所以你可能会这样:

    resource.h:

    // Other defines...
    
    #define TEXTFILE        256
    #define IDR_MYTEXTFILE  101
    

    在你的资源文件中:

    #include "resource.h"
    
    // Other resource statements...
    
    IDR_MYTEXTFILE TEXTFILE "mytextfile.txt"
    

    然后你像这样加载它(为了清楚起见省略了错误检查代码):

    #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;
    }
    

    请注意,您实际上不必释放资源,因为资源驻留在可执行文件的二进制文件中,系统会在程序退出时自动删除它们(函数 FreeResource() 在 32 位和 64位 Windows 系统)。

    由于数据驻留在可执行二进制文件中,您无法直接通过检索到的指针对其进行修改(这就是LoadFileInResource() 函数实现将指针存储在const char* 中的原因)。您需要使用BeginUpdateResource()UpdateResource()EndUpdateResource() 函数来执行此操作。

    【讨论】:

    • 我还有一个更普遍的疑问问here。您能否回答我的第二个与您的回答相关的问题?只是如何拥有一个 dll 文件,该文件具有包含答案中 main 中的代码的功能。
    • " 程序退出时系统会自动删除" 难道所有程序退出系统都没有资源吗?内存泄漏和资源泄漏发生在可执行文件的执行过程中。因此,如果该程序加载 n 个相同的资源,它将引发资源泄漏。
    • 在资源文件的属性中有“Null Terminate Strings”
    • 我有一个 win32 应用程序。我可以知道在哪里可以找到资源文件以及如何创建用户定义的资源文件吗?我想在构建过程中加载一个 xml 文件。文件大小为 20MB。
    【解决方案2】:

    您可以使用xxd(来自 linux 机器或可能来自 cygwin)生成 .h/.cc 文件的数据。

    有很多堆栈溢出问题对此进行了详细扩展:

    【讨论】:

    • -1 PE(+) 文件已经能够存储自定义资源,Windows 构建工具拥有您需要的一切。资源脚本语法已记录在案,操作系统提供了用于访问该数据的 API。这个答案是另一个问题的答案。
    猜你喜欢
    • 2012-06-26
    • 2017-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多