C++ 如何将文件嵌入到可执行文件中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7288279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:44:25  来源:igfitidea点击:

How to embed a file into an executable?

c++fileexecutable

提问by Anne Quinn

I have a small demo executable wrote in C++ that depends only on one 5kb PNG image being loaded before it can run, which is used for a pixel text I made. Because of this one file, I would need to give out a ZIP archive instead of just one executable file, which creates enough friction between download and 'play' that I believe would dissuade some from trying it out.

我有一个用 C++ 编写的小型演示可执行文件,它仅依赖于在运行之前加载的一个 5kb PNG 图像,该图像用于我制作的像素文本。由于这个文件,我需要提供一个 ZIP 存档而不是一个可执行文件,这会在下载和“播放”之间产生足够的摩擦,我相信这会阻止一些人尝试它。

My question is, is there anyway to embed the PNG file (and any other file really) into the Executable or source code so that it is a single file, and the executable can use it?

我的问题是,无论如何将 PNG 文件(以及任何其他文件)嵌入到可执行文件或源代码中,使其成为单个文件,并且可执行文件可以使用它?

I have the ability to parse the PNG as a byte stream, so it does not need converted to pixel data.

我有能力将 PNG 解析为字节流,因此它不需要转换为像素数据。

Thanks in advance! (Other questions with a similar title to this exist, but they and their answers seem to get into more specific issues and weren't very helpful)

提前致谢!(存在与此类似标题的其他问题,但它们及其答案似乎涉及更具体的问题并且不是很有帮助)

edit:The compiler is Visual C++ 2010 and this is on Windows (though I would want to avoid windows specific utilities for this)

编辑:编译器是 Visual C++ 2010,这是在 Windows 上(尽管我想避免使用 Windows 特定的实用程序)

edit2: Alf's answer seemed like the most portable method, so I quickly wrote a function to parse the PNG file into a TXT or header file that could be read as a unsigned chararray. It appears to be identical in this form to the PNG file itself, but my png loader won't accept the array. When loading it from memory, the PNG parser takes a (void * buffer, size_t length)if it matters.

edit2:Alf 的答案似乎是最便携的方法,所以我很快编写了一个函数来将 PNG 文件解析为可以作为unsigned char数组读取的 TXT 或头文件。在这种形式下,它似乎与 PNG 文件本身相同,但我的 png 加载器不接受该数组。当从内存中加载它时,PNG 解析器(void * buffer, size_t length)如果重要的话会取一个。

The code if you wanted to see, but I'll still accept other answers if you think they're better than this method:

如果您想查看代码,但如果您认为它们比这种方法更好,我仍然会接受其他答案:

void compileImagePNGtoBinary(char * filename, char * output){

    FILE * file = fopen(filename, "rb");
    FILE * out = fopen(output, "w");

    unsigned char buffer[32];
    size_t count;
    fprintf(out, "#pragma once \n\n static unsigned char TEXT_PNG_BYTES[] = { ");
    while(!feof(file)){
            count = fread(buffer, 1, 32, file);

            for(int n = 0; n < count; ++n){
                    fprintf(out, "0x%02X, ", buffer[n]);
            };
    };
    fprintf(out, "};");
    fclose(file);
    fclose(out);

};

Final Edit: ImageMagickwhich Alf also mentioned did exactly what I needed of it, thanks!

最终编辑:Alf 也提到的ImageMagick正是我所需要的,谢谢!

采纳答案by Cheers and hth. - Alf

A portable way is to define a function like

一种可移植的方式是定义一个函数,如

typedef unsigned char Byte;

Byte const* pngFileData()
{
    static Byte const data =
    {
        // Byte data generated by a helper program.
    };
    return data;
}

Then all you have to do is to write a little helper program that reads the PNG file as binary and generates the C++ curly braces initializer text. Edit: @awoodland has pointed out in comment to the question, that ImageMagickhas such a little helper program…

然后,您所要做的就是编写一个小助手程序,该程序将 PNG 文件读取为二进制文件并生成 C++ 花括号初始值设定项文本。编辑:@awoodland 在对该问题的评论中指出,ImageMagick有这样一个小助手程序......

Of course, for a Windows-specific program, instead use the ordinary Windows resource scheme.

当然,对于特定于 Windows 的程序,请改用普通的 Windows 资源方案。

Cheers & hth.,

干杯 & hth.,

回答by Roddy

Look at XD:

看看XD:

http://www.fourmilab.ch/xd/

http://www.fourmilab.ch/xd/

Finally, xd can read a binary file and emit a C language data declaration which contains the data from the file. This is handy when you wish to embed binary data within C programs.

最后,xd 可以读取二进制文件并发出包含文件数据的 C 语言数据声明。当您希望在 C 程序中嵌入二进制数据时,这很方便。

Personally, I'd use resources for windows, but if you require a truly portable way that doesn't involve knowledge of the executable format, this is the way to go. PNG, JPG, whatever...

就我个人而言,我会使用 Windows 的资源,但如果您需要一种真正可移植的方式,而不涉及可执行格式的知识,这就是要走的路。PNG,JPG,随便...

回答by fabrizioM

Base64encode the file and put it in a string somewhere in your code ;)

Base64对文件进行编码并将其放入代码中某处的字符串中;)

回答by Mark Ransom

You can embed any arbitrary file into your program resources: (MSDN) User-Defined Resource.

您可以将任意文件嵌入到您的程序资源中:(MSDN) User-Defined Resource

A user-defined resource-definition statement defines a resource that contains application-specific data. The data can have any format and can be defined either as the content of a given file (if the filename parameter is given) or as a series of numbers and strings (if the raw-data block is specified).

nameID typeID filename

The filename specifies the name of a file containing the binary data of the resource. The contents of the file are included as the resource. RC does not interpret the binary data in any way. It is the programmer's responsibility to ensure that the data is properly aligned for the target computer architecture.

用户定义的资源定义语句定义包含应用程序特定数据的资源。数据可以有任何格式,可以定义为给定文件的内容(如果给定文件名参数)或一系列数字和字符串(如果指定了原始数据块)。

nameID typeID filename

文件名指定包含资源二进制数据的文件名。文件的内容作为资源包含在内。RC 不会以任何方式解释二进制数据。程序员有责任确保数据与目标计算机体系结构正确对齐。

Once you've done that you can use the LoadResource functionto access the bytes contained in the file.

完成后,您可以使用LoadResource 函数访问文件中包含的字节。

回答by Puppy

This is executable-format dependent, which means inherently operating system/compiler dependent. Windows offers the Resources system for this as mentioned in this question.

这是依赖于可执行格式的,这意味着本质上依赖于操作系统/编译器。如本问题所述,Windows 为此提供了资源系统。

回答by jozxyqk

On linux I use this. It's based off a few examples I found when trying to do some 4k demos, albeit modified a bit. I believe it can work on windows too, but not with the default VS inline assembly. My workaround is #defining a macro to either use this code or the windows resource system that @MarkRansomsuggests (quite painful to get working, but does work eventually).

在 linux 上我使用这个。它基于我在尝试进行一些 4k 演示时发现的一些示例,尽管做了一些修改。我相信它也可以在 Windows 上运行,但不适用于默认的 VS 内联程序集。我的解决方法是 #defining 一个宏来使用此代码或@MarkRansom建议的 Windows 资源系统(开始工作非常痛苦,但最终确实有效)。

//USAGE: call BINDATA(name, file.txt) and access the char array &name.

#ifndef EMBED_DATA_H
#define EMBED_DATA_H

#ifdef _WIN32
//#error The VS ASM compiler won't work with this, but you can get external ones to do the trick
#define BINDATA #error BINDATA requires nasm
#else

__asm__(
".altmacro\n" \
".macro binfile p q\n" \
"   .global \p\n" \
"\p:\n" \
"   .incbin \q\n" \
"\p&_end:\n" \
"   .byte 0\n" \
"   .global \p&_len\n" \
"\p&_len:\n" \
"   .int(\p&_end - \p)\n" \
".endm\n\t"
);

#ifdef __cplusplus
    extern "C" {
#endif

#define BINDATA(n, s) \
__asm__("\n\n.data\n\tbinfile " #n " \"" #s "\"\n"); \
extern char n; \
extern int n##_len;

#ifdef __cplusplus
    }
#endif

#endif

#endif