Как хранить данные внутри исполняемого файла - PullRequest
7 голосов
/ 11 апреля 2010

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

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

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

Ответы [ 11 ]

8 голосов
/ 11 апреля 2010

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

int external_data[] =
{
    ...
};

вы можете указать компилятору, сколько элементов содержится во внешних данных:

size_t external_data_max_idx = sizeof(external_data) / sizeof(*external_data);
5 голосов
/ 11 апреля 2010

Вы можете просто создать определение массива. Например, предположим, что у вас есть 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
4 голосов
/ 11 апреля 2010

Сохраните его как массив 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 голосов
/ 11 апреля 2010

Вы можете использовать команду xxd с опцией -i, чтобы преобразовать любой файл в вектор символов в C. Если вы используете Windows, вы можете использовать ее в Cygwin.

2 голосов
/ 11 апреля 2010

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

Первый этап: написать приложение, которое вызывает 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, вероятно, не работает. Я не проверял это. * Если вы используете Windows или Mac, вы, вероятно, можете сделать что-то похожее с системой ресурсов (у MAC аналогичная вещь нет?)

1 голос
/ 11 апреля 2010

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

0 голосов
/ 25 октября 2013

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

0 голосов
/ 12 апреля 2010

Не решение (это было дано ранее), но: не помещайте его в заголовочный файл. Напишите заголовок, который определяет функцию, которая возвращает массив. Затем реализуйте это в файле .c. В противном случае вы попадете в беспорядок компиляции ...

0 голосов
/ 11 апреля 2010

На какой платформе вы работаете? Если вы работаете в Windows и числа не изменятся во времени, просто поместите ваш текстовый файл в ресурсы программы с помощью компоновщика ресурсов и прочитайте его в своем коде.

0 голосов
/ 11 апреля 2010

Вы можете адаптировать это решение к номерам:

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