在exe文件中嵌入一个文本文件,可以使用fopen访问

时间:2011-09-09 19:13:08

标签: c++ header

我想将包含一些数据的文本文件嵌入到我的程序中。 我们称之为“ data.txt ”。

这个文本文件通常加载一个函数,该函数需要文本文件的文件名作为输入,并最终使用fopen()调用打开...某些内容

FILE* name = fopen("data.txt");

我无法真正更改此功能,我希望例程在每次运行时打开同一个文件。我见过有人问过将文件嵌入标题,但似乎我无法在嵌入标题的文件中调用fopen()。

所以我的问题是:有没有办法将文本文件作为可调用的文件/变量嵌入fopen()?

我正在使用VS2008。

3 个答案:

答案 0 :(得分:2)

是和否。最简单的方法是将文本文件的内容转换为初始化数组。

char data_txt[] = {
    'd','a','t','a',' ','g','o','e','s',' ','h','e','r','e', //....
};

使用小型perl脚本甚至是小型C程序即可轻松完成此转换。然后编译并将生成的模块链接到您的程序中。

使用Makefile更容易管理的一个老技巧是让脚本将其数据转换为初始化程序的 body ,并将其写入文件而不包含周围的变量声明,甚至是大括号。如果将data.txt转换为data.inc,则会像以下一样使用它:

char data_txt[] = {
#include "data.inc"
};

<强>更新

在许多平台上,可以将任意数据附加到可执行文件本身。然后诀窍是在运行时找到它。在可能的平台上,将存在可执行文件的文件头信息,其指示可执行映像的长度。在打开可执行文件进行读取后,可用于计算与fseek()一起使用的偏移量。以便携方式进行操作更加困难,因为甚至无法以可移植的方式在运行时学习可执行映像的实际文件名。 (提示,argv[0]不需要指向实际程序。)

如果您无法避免对fopen()的调用,那么您仍然可以使用此技巧保留data.txt内容的副本,并在运行时将其放回文件中。你甚至可以聪明,只有在文件丢失时才写文件。

如果您可以将来电置于fopen(),但仍然需要FILE *指向数据,那么很可能如果您愿意快速和宽松地玩使用您的C运行时库的stdio实现。在GNU版本的libc中,sprintf()sscanf()等函数实际上是通过创建一个“足够真实”FILE *来实现的,可以传递给一个公共实现(vfprintf()vfscanf(),IIRC)。伪造的FILE被标记为缓冲,并将其缓冲区指向用户的缓冲区。一些魔法用于确保stdio的其余部分不会做任何愚蠢的事情。

答案 1 :(得分:1)

对于任何类型的文件,基于RBerteig anwser你可以用python做一些简单的事情:

该程序将生成一个text.txt.c文件,该文件可以编译并链接到您的代码,将任何文本或二进制文件直接嵌入到您的exe中,并直接从变量中读取它:

import struct;                  #    Needed to convert string to byte

f = open("text.txt","rb")       #    Open the file in read binary mode
s = "unsigned char text_txt_data[] = {"

b = f.read(1)                   #    Read one byte from the stream
db = struct.unpack("b",b)[0]     #    Transform it to byte
h = hex(db)                      #    Generate hexadecimal string
s = s + h;                      #    Add it to the final code
b = f.read(1)                   #    Read one byte from the stream

while b != "":
    s = s + ","                 #    Add a coma to separate the array
    db = struct.unpack("b",b)[0] #    Transform it to byte
    h = hex(db)                  #    Generate hexadecimal string
    s = s + h;                  #    Add it to the final code
    b = f.read(1)               #    Read one byte from the stream

s = s + "};"                     #    Close the bracktes
f.close()                       #    Close the file

# Write the resultan code to a file that can be compiled
fw = open("text.txt.c","w");   
fw.write(s);
fw.close();

会产生类似

的内容
unsigned char text_txt_data[] = {0x52,0x61,0x6e,0x64,0x6f,0x6d,0x20,0x6e,0x75...

您可以使用带有如下代码的变量在另一个c文件中使用您的数据:

extern unsigned char text_txt_data [];

目前我无法想到将其转换为可读文本的两种方法。使用内存流或将其转换为c-string。

答案 2 :(得分:0)

不,没有这种可能性。这就是为什么C ++有自己的方式来读取文件:std::ifsteam。如果您的代码使用它,您可以轻松地将其更改为std::istringstream以从内存字符串而不是文件中读取数据。