Как хранить данные в исполняемом файле
Мне нужно найти способ сохранить 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. В противном случае, вы окажетесь в беспорядке компиляции...
просто сделайте строку из того, сколько символов в вашей исполняемой программе, а затем откройте другой раздел программы в виде файла, возьмите байты, найдите строку, которую вы скомпилировали, и измените ее, как вы хотите напрямую (обязательно поместите туда уникальную строку для размещения фактической области со строкой в двоичном формате), возможно, потребуется закрыть программу после выполнения другой программы, которая записывает данные в исходную программу и повторно выполняет ее, когда исходная программа повторно выполняется, она может читать новые написанные значения из строки, которая была объявлена в двоичном формате, и использовать это для выполнения каких-либо задач.