如何在可执行文件中存储数据

我需要找到一种方法来在程序的可执行文件中存储250 KB的纯文本数字。

通常,我会将数据放在一个单独的文件中,让程序在运行时读取它,但这不是一个选项。 相反,程序和数据需要在一个可执行文件中。

我完全不知道怎么做(除了写250.000 #defines :-),我很感激任何建议。

某种数组怎么样? 只需将该定义放在一个文件中并将其编译到您的程序中:

int external_data[] = { ... }; 

您可以让编译器告诉您外部数据中有多少元素:

 size_t external_data_max_idx = sizeof(external_data) / sizeof(*external_data); 

你可以生成一个数组定义。 例如,假设您有numbers.txt

 $ head -5 numbers.txt 0.99043748698114 0.0243802034269436 0.887296518349228 0.0644020236531517 0.474582201929554 

我使用以下示例生成了它:

 $ perl -E'say rand() for (1..250_000)' >numbers.txt 

然后将其转换为C数组定义,您可以使用脚本:

 $ perl -lpE'BEGIN{ say "double data[] = {"; }; > END{ say "};" }; > s/$/,/' > data.h < numbers.txt 

它产生:

 $ head -5 data.h double data[] = { 0.99043748698114, 0.0243802034269436, 0.887296518349228, 0.0644020236531517, $ tail -5 data.h 0.697015237317363, 0.642250552146166, 0.00577098769553785, 0.249176256744811, }; 

它可以在您的程序中使用如下:

 #include  #include "data.h" int main(void) { // print first and last numbers printf("%g %g\n", data[0], data[sizeof(data)/sizeof(*data)-1]); return 0; } 

运行:

 $ gcc *.c && ./a.out 0.990437 0.249176 

将其存储为const数组:

 /* Maximum number of digits in a number, adjust as necessary */ #define NUMBER_MAX_LENGTH 16 /* How many numbers you have (in this case 250K), adjust as necessary */ #define NUMBER_OF_NUMBERS (250 * (1 << 10)) const char data[NUMBER_OF_NUMBERS][NUMBER_MAX_LENGTH+1] = { "12345", "2342841", "129131", "18317", /* etc */ }; 

大概你知道你的数据集,所以你可以在你的情况下为NUMBER_MAX_LENGTH提供适当的值。

您当然也可以编写一个脚本,将数字的平面文件转换为此格式。 如果需要,您甚至可以将数字保存在纯文本数据文件中,并让脚本在构建期间生成相应的C代码。

我这样写是因为你说“纯文本数字”,表明你出于某种原因需要它们作为字符串。 如果你宁愿把它们作为整数,那就更简单了:

 /* How many numbers you have (in this case 250K), adjust as necessary */ #define NUMBER_OF_NUMBERS (250 * (1 << 10)) const int data[NUMBER_OF_NUMBERS] = { 12345, 2342841, 129131, 18317, /* etc */ }; 

假设你的数字都没有太大而不能存储在int中。

您可以使用带有-i选项的xxd命令将任何文件转换为C的char向量。 如果你在Windows上,你可以考虑在Cygwin中使用它。

让我们假设数字是常数。 让我们假设您可以在“预编译”阶段计算此列表一次。 让我们假设有一个函数可以“返回”该列表。

第一阶段:编写一个调用getFooNumber()并完美运行的应用程序。 尼斯。

第二阶段:获取该function,并将其放入另一个项目中。 现在,让我们编写一个小应用程序,它将生成250,000行C代码。

 #include  #define MAX_BLABLA 2500000 int main(int argc, char *argv[] ) { FILE *f fopen("fooLookupTable.h"); long i; fprintf( f, "#ifndef FOO_HEADER\n"); fprintf( f, "#define FOO_HEADER\n"); fprintf( f, "char [] blabla = {\n\t"); for( i=0; i 

这将创建Billy ONeal谈到的名单。

阶段3:使用您刚刚在阶段2中创建的头文件,并在第一个项目中使用它从新的getFooNumber()返回查找表中的值。

第4阶段:学习使用Qt,并了解您可以直接嵌入文件并使用QFile(“:application / numberz.txt”)加载它。

注意:* C代码可能已损坏。 我没有测试它。 *如果您使用的是Windows或Mac,您可以使用与资源系统类似的东西(MAC有类似的东西没有?)

我同意以前的答案。 最好的方法是将其存储在代码中,然后将其编译到程序中。 为了争论,您可以查看可执行文件的格式并在其中添加一些数据/代码(这是许多病毒的工作方式),只需从可执行文件中读取并获取数据即可。 http://refspecs.freestandards.org/elf/elf.pdf具有可执行文件的格式。 这再次是为了争论,不推荐。

听起来你正试图避免将它放在源文件中,但这正是我要做的:

 int numbers[250000] = {1, 2, ...}; 

技术上可以将它们保存为普通文件并编写链接器指令文件,该文件创建适当大小的新数据部分并将它们组合起来,但实际上没有理由。 将该定义放在一个单独的文件中,并将#include到需要它的文件中

您可以将此解决方案调整为数字:

 static const wchar_t *systemList[] = { L"actskin4.ocx", L"advpack.dll", L"asuninst.exe", L"aswBoot.exe", L"AvastSS.scr", L"avsda.dll", L"bassmod.dll", L"browseui.dll", L"CanonIJ Uninstaller Information", L"capicom.dll", L"cdfview.dll", L"cdm.dll", L"d3dx9_24.dll", L"d3dx9_25.dll", L"d3dx9_27.dll", L"d3dx9_28.dll", L"d3dx9_29.dll", L"d3dx9_30.dll", L"danim.dll", L"dfrgntfs.exe", L"dhcpcsvc.dll", L"dllhost.exe", L"dnsapi.dll", L"drivers\\aavmker4.sys", L"drivers\\apt.sys", L"drivers\\aswFsBlk.sys", L"drivers\\aswmon.sys", L"drivers\\aswmon2.sys", L"drivers\\aswRdr.sys", L"drivers\\aswSP.sys", L"drivers\\aswTdi.sys", L"drivers\\avg7core.sys", L"drivers\\avg7rsw.sys", L"drivers\\avg7rsxp.sys", L"drivers\\avgclean.sys", L"drivers\\avgmfx86.sys", L"drivers\\avgntdd.sys", L"drivers\\avgntmgr.sys", L"drivers\\avgtdi.sys", L"drivers\\avipbb.sys", L"drivers\\cmdmon.sys", L"drivers\\gmer.sys", L"drivers\\inspect.sys", L"drivers\\klick.sys", L"drivers\\klif.sys", L"drivers\\klin.sys", L"drivers\\pxcom.sys", L"drivers\\pxemu.sys", L"drivers\\pxfsf.sys", L"drivers\\pxrd.sys", L"drivers\\pxscrmbl.sys", L"drivers\\pxtdi.sys", L"drivers\\rrspy.sys", L"drivers\\rrspy64.sys", L"drivers\\ssmdrv.sys", L"drivers\\UMDF", L"drivers\\USBSTOR.SYS", L"DRVSTORE", L"dxtmsft.dll", L"dxtrans.dll", L"en-us", L"extmgr.dll", L"fntcache.dat", L"hal.dll", L"icardie.dll", L"ie4uinit.exe", L"ieakeng.dll", L"ieaksie.dll", L"ieakui.dll", L"ieapfltr.dat", L"ieapfltr.dll", L"iedkcs32.dll", L"ieframe.dll", L"iepeers.dll", L"iernonce.dll", L"iertutil.dll", L"ieudinit.exe", L"ieui.dll", L"imon1.dat", L"inseng.dll", L"iphlpapi.dll", L"java.exe", L"javaw.exe", L"javaws.exe", L"jgdw400.dll", L"jgpl400.dll", L"jscript.dll", L"jsproxy.dll", L"kbdaze.dll", L"kbdblr.dll", L"kbdbu.dll", L"kbdkaz.dll", L"kbdru.dll", L"kbdru1.dll", L"kbdtat.dll", L"kbdur.dll", L"kbduzb.dll", L"kbdycc.dll", L"kernel32.dll", L"legitcheckcontrol.dll", L"libeay32_0.9.6l.dll", L"Macromed", L"mapi32.dll", L"mrt.exe", L"msfeeds.dll", L"msfeedsbs.dll", L"msfeedssync.exe", L"msftedit.dll", L"mshtml.dll", L"mshtmled.dll", L"msrating.dll", L"mstime.dll", L"netapi32.dll", L"occache.dll", L"perfc009.dat", L"perfh009.dat", L"pncrt.dll", L"pndx5016.dll", L"pndx5032.dll", L"pngfilt.dll", L"px.dll", L"pxcpya64.exe", L"pxdrv.dll", L"pxhpinst.exe", L"pxinsa64.exe", L"pxinst.dll", L"pxmas.dll", L"pxsfs.dll", L"pxwave.dll", L"rasadhlp.dll", L"rasmans.dll", L"riched20.dll", L"rmoc3260.dll", L"rrsec.dll", L"rrsec2k.exe", L"shdocvw.dll", L"shell32.dll", L"shlwapi.dll", L"shsvcs.dll", L"sp2res.dll", L"spmsg.dll", L"ssiefr.EXE", L"STKIT432.DLL", L"streamhlp.dll", L"SWSC.exe", L"tzchange.exe", L"url.dll", L"urlmon.dll", L"vsdata.dll", L"vsdatant.sys", L"vsinit.dll", L"vsmonapi.dll", L"vspubapi.dll", L"vsregexp.dll", L"vsutil.dll", L"vswmi.dll", L"vsxml.dll", L"vxblock.dll", L"webcheck.dll", L"WgaLogon.dll", L"wgatray.exe", L"wiaservc.dll", L"windowspowershell", L"winfxdocobj.exe", L"wmp.dll", L"wmvcore.dll", L"WREGS.EXE", L"WRLogonNtf.dll", L"wrlzma.dll", L"wuapi.dll", L"wuauclt.exe", L"wuaueng.dll", L"wucltui.dll", L"wups.dll", L"wups2.dll", L"wuweb.dll", L"x3daudio1_0.dll", L"xactengine2_0.dll", L"xactengine2_1.dll", L"xactengine2_2.dll", L"xinput1_1.dll", L"xinput9_1_0.dll", L"xmllite.dll", L"xpsp3res.dll", L"zlcomm.dll", L"zlcommdb.dll", L"ZPORT4AS.dll" }; 

你在运行什么平台? 如果您在Windows上并且数字不会及时更改,那么只需使用资源链接器将文本文件放入程序资源,然后在代码中读取它。

不是解决方案(这是之前给出的)但是:不要将它放在头文件中。 编写标题,定义返回数组的函数。 然后在.c文件中实现它。 否则,你最终将陷入编译混乱……

只需在你的可执行程序中创建一个包含多个字符的字符串,然后让程序的另一部分打开它自己作为文件,抓取字节,找到你编译的字符串,然后直接改变它(确保放置)一个唯一的字符串,用于定位二进制字符串的实际区域),可能需要在执行另一个程序后关闭程序,该程序将数据写入原始程序并重新执行,当重新执行原始程序时它可以从字符串中读取新的写入值,该字符串在其二进制文件中声明,并使用它来执行任务。