Как хранить данные в исполняемом файле

Мне нужно найти способ сохранить 250 КБ простых текстовых чисел в исполняемом файле моей программы.

обычно я помещаю данные в отдельный файл и позволяю программе читать его во время работы, но это не вариант здесь. Вместо этого программа и данные должны быть в одном исполняемом файле.

Я понятия не имею, как это сделать (кроме написания 250.000 #defines: -), и я был бы признателен за любые предложения.

11 ответов


Как насчет некоторого массива. Просто поместите это определение в файл и скомпилируйте его в свою программу:

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

сохраните его как массив 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.



предположим, что числа являются константами. Предположим, что вы можете вычислить этот список один раз, на этапе "предварительной компиляции". Предположим, что есть функция, которая может "вернуть" этот список.

этап: напишите приложение, которое вызывает 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");
}

Это составьте список, о котором говорил Билли Онеал.

Этап 3: Используйте файл заголовка, который вы только что создали на этапе 2, и используйте его внутри первого проекта, чтобы вернуть из нового getFooNumber() значение из таблицы подстановки.

Этап 4: Научитесь использовать Qt и поймите, что вы можете встроить файл напрямую и загрузить его с помощью QFile(":application/numberz.формат txt.)"

заметки: * Код C, вероятно, сломан. Я не проверял его. * Если вы usign Windows или Mac, вы можете вероятно, сделать что-то подобное с ресурсной системой (MAC имеет аналогичную вещь нет?)


Я согласен с предыдущими ответами. Лучший способ-просто сохранить его в коде, а затем скомпилировать его в программу. Для аргумента вы можете посмотреть формат исполняемого файла и добавить туда некоторые данные/код (так работает много вирусов) и просто прочитать из исполняемого файла и получить данные. http://refspecs.freestandards.org/elf/elf.pdf имеет формат для исполняемого файла. Еще раз повторюсь, что это ради аргументации и не рекомендуется.


похоже, вы пытаетесь избежать размещения его в исходном файле, но это именно то, что я бы сделал:

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

технически возможно сохранить их как простой файл и написать файл директивы компоновщика, который создает новый раздел данных надлежащего размера и объединяет их, но на самом деле нет причин. Поставил это определение в отдельный файл и включать его в файл, который в ней нуждается


можно адаптировать данное решение с номерами:

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. В противном случае, вы окажетесь в беспорядке компиляции...


просто сделайте строку из того, сколько символов в вашей исполняемой программе, а затем откройте другой раздел программы в виде файла, возьмите байты, найдите строку, которую вы скомпилировали, и измените ее, как вы хотите напрямую (обязательно поместите туда уникальную строку для размещения фактической области со строкой в двоичном формате), возможно, потребуется закрыть программу после выполнения другой программы, которая записывает данные в исходную программу и повторно выполняет ее, когда исходная программа повторно выполняется, она может читать новые написанные значения из строки, которая была объявлена в двоичном формате, и использовать это для выполнения каких-либо задач.