如何将文件嵌入可执行文件?

时间:2011-09-02 19:18:43

标签: c++ file executable

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

我的问题是,无论如何都要将PNG文件(以及任何其他文件)真正嵌入到可执行文件或源代码中,以便它是一个文件,可执行文件可以使用它吗?

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

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

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

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

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

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);

};

最终修改ImageMagick Alf也提到了我所需要的,谢谢!

6 个答案:

答案 0 :(得分:10)

便携式方法是定义类似

的功能
typedef unsigned char Byte;

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

然后你要做的就是写一个小帮助程序,将PNG文件作为二进制文件读取,并生成C ++花括号初始化文本。 编辑:@awoodland在评论中指出,ImageMagick有一个小帮手程序......

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

干杯&amp;第h。,

答案 1 :(得分:9)

看看XD:

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

  

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

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

答案 2 :(得分:5)

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

答案 3 :(得分:4)

这是依赖于可执行文件的,这意味着依赖于操作系统/编译器。 Windows为此提供了资源系统,如this question中所述。

答案 4 :(得分:3)

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

  

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

nameID typeID filename
     

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

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

答案 5 :(得分:0)

在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