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

时间:2010-04-11 18:31:35

标签: c storage executable

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

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

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

11 个答案:

答案 0 :(得分:8)

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

int external_data[] =
{
    ...
};

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

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

答案 1 :(得分:5)

您可以生成数组定义。例如,假设您有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 <stdio.h>    
#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

答案 2 :(得分:4)

将其存储为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中。

答案 3 :(得分:3)

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

答案 4 :(得分:2)

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

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

第二阶段: 拿这个功能,把它放在另一个项目中。现在,让我们编写一个小应用程序,它将生成250,000行C代码。

#include <stdlib>
#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<MAX_BLABLA; i ++ )
  {
     fprintf(f, "%d", getFooNumber(i) );
     if (n+1 != MAX_BLABLA)
         fprintf(f, ",");
     if (n%10 == 0)
         fprintf(f, "\n\t");
  }
  fprintf( f, "};\n\n");
  fprintf( f, "#endif // FOO_HEADER\n");
}

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

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

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

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

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

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

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

答案 7 :(得分:0)

您可以将this solution改为数字:

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"
};

答案 8 :(得分:0)

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

答案 9 :(得分:0)

不是解决方案(之前已经提供过),但是:不要将它放在头文件中。编写标题,定义返回数组的函数。然后在.c文件中实现它。否则,你最终会陷入汇编......

答案 10 :(得分:0)

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