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

embedding a text file in an exe which can be accessed using fopen

本文关键字:文件 文本 可以使 访问 fopen 一个 EXE      更新时间:2023-10-16

我想在我的程序中嵌入一个包含一些数据的文本文件。我们称之为">数据.txt"。

此文本文件通常加载一个函数,该函数需要文本文件的文件名作为输入,并最终使用 fopen(( 调用打开...一些东西的线条

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

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

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

我正在使用VS2008。

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

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

这种转换很容易用一个小的perl脚本甚至一个小的C程序来完成。然后,编译生成的模块并将其链接到程序中。

使用

Makefile 使其更易于管理的一个古老技巧是使脚本将其数据转换为初始值设定项的主体,并将其写入文件,而不使用周围的变量声明甚至大括号。如果data.txt转换为 data.inc ,则按如下方式使用:

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

更新

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

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

如果您可以放弃对fopen()的调用,但仍需要一个指向数据的FILE *,那么如果您愿意快速而松散地使用 C 运行时库的 stdio 实现,这可能是可能的。在 libc 的 GNU 版本中,像 sprintf()sscanf() 这样的函数实际上是通过创建一个"足够真实"的FILE *来实现的,该可以传递给一个共同的实现(vfprintf()vfscanf(),IIRC(。该伪造FILE被标记为已缓冲,并将其缓冲区指向用户的缓冲区。一些魔法被用来确保stdio的其余部分不会做任何愚蠢的事情。

对于任何类型的文件,基于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 文件中使用您的数据:

外部无符号字符text_txt_data[];

现在我想不出两种将其转换为可读文本的方法。使用内存流或将其转换为 c 字符串。