2010-04-11 23 views
7

Necesito encontrar una manera de almacenar 250 KB de números de texto sin formato dentro del archivo ejecutable de mi programa.Cómo almacenar datos dentro del archivo ejecutable

Por lo general, me volvería a poner los datos en un archivo separado y dejar que el programa lo leyó mientras se está ejecutando, pero eso no es una opción aquí. En cambio, el programa y los datos deben estar en un archivo ejecutable.

me tienen absolutamente ninguna idea de cómo hacerlo (excepto escribir 250.000 #defines :-) y lo agradecería cualquier sugerencia.

+2

¿Qué plataforma?podría usar recursos de Win32, por ejemplo? –

+1

Pregunta similar (plug desvergonzado): http://stackoverflow.com/questions/2481998/how-do-i-include-extremely-long-literals-in-c-source –

+1

Para todos aquellos que sugirieron usar una matriz, pensé en eso también, pero me desanimé por el largo tiempo de compilación. Supongo que fue justo después de todo. ¡gracias! – michael

Respuesta

9

¿Qué tal una matriz de algún tipo. Sólo hay que poner esa definición en un archivo y compilarlo en su programa:

int external_data[] = 
{ 
    ... 
}; 

que puede tener el compilador te dice cuántos elementos hay en los datos externa:

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

+1 para usar la sintaxis del bracket vacío. –

+0

+1 para sugerir la definición en un * archivo * separado. Actualmente estoy usando esta técnica y solo tengo que cambiar el archivo y reconstruir, especialmente cuando los datos cambian. –

4

tienda como una matriz 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 */ }; 

Es de suponer que conoce el conjunto de datos para que pueda llegar con el valor apropiado para NUMBER_MAX_LENGTH en su caso.

Puede también, por supuesto, escribir un script que transforma un archivo plano de los números en este formato. Si lo desea, puede guardar los números en un archivo de datos de texto sin formato y hacer que el script genere el código C correspondiente como se indicó anteriormente durante su compilación.

lo escribí de esa manera porque usted ha dicho "números de texto sin formato", lo que indica que los necesite como cadenas por alguna razón. Si prefiere tener como números enteros, es aún más simple:

/* 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 */ }; 

asumiendo que ninguno de sus números es demasiado grande como para guardar en un int.

+3

Puede simplemente usar 'data []' en lugar de usar una cantidad de números macro. –

0

Parece que usted está tratando para evitar poner en un archivo de origen, pero eso es exactamente lo que haría:

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

es técnicamente posible para mantenerlos como un archivo normal y escribir un archivo de directiva enlazador que crea una nueva d una sección del tamaño adecuado y las combina, pero realmente no hay ninguna razón. Puesto que la definición en un archivo separado y # include en el archivo que lo necesita

+1

Tenga en cuenta que podría hacer que "números []' y el compilador cuenten para usted. –

+0

Sí, pero si sé cuántas cosas se supone que deben estar en la matriz, me gusta incluirlas, para que las personas que la miren sepan el tamaño de inmediato, y si me equivoco y olvido/duplico obtendré un error en tiempo de compilación –

0

Se pueden adaptar this solution a los números:

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

Estoy de acuerdo con las respuestas anteriores. La mejor manera es simplemente almacenarlo en el código y luego compilarlo en el programa. En aras de la discusión, podría ver el formato de un ejecutable y agregar algunos datos/códigos allí (así es como funcionan muchos virus) y simplemente leer desde el ejecutable y obtener los datos. http://refspecs.freestandards.org/elf/elf.pdf tiene el formato de un ejecutable. Una vez más esto es por el bien de la discusión y no es recomendable.

2

Supongamos que los números son constantes. Supongamos, que puede calcular esta lista una vez, en la etapa de "precompilación". Supongamos que hay una función que puede "devolver" esa lista.

Primera etapa: escribir una aplicación que llama getFooNumber() y funciona perfectamente. Bonito.

Etapa dos: Tome esa función y colóquela en otro proyecto. Ahora, escribamos una pequeña aplicación que generará las 250,000 líneas de código 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"); 
} 

Esto creará la lista de la que habló Billy ONeal.

Etapa 3: Utilice el archivo de encabezado que acaba de crear en la etapa 2, y úselo dentro del primer proyecto para devolver desde el nuevo getFooNumber() el valor de la tabla de búsqueda.

Etapa 4: Aprenda a usar Qt, y entienda que puede incrustar el archivo directamente y cargarlo usando QFile (": application/numberz.txt").

Notas: * El código C probablemente está roto. No lo probé. * Si usa Windows o Mac, probablemente pueda hacer algo similar con el sistema de recursos (MAC tiene una cosa similar no?)

+0

+1, creando un pequeño programa para generar código C a partir de datos es muy útil. – nos

5

Puede generar una definición de matriz. Por ejemplo, suponga que tiene numbers.txt:

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

he generado por el ejemplo usando:

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

A continuación, para convertirlo en C definición de la matriz se puede utilizar una secuencia de comandos:

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

produce:

$ 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, 
}; 

Podría ser utilizado en el programa de la siguiente manera:

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

Run que:

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

++ para la generación de código –

0

¿En qué plataforma estás corriendo a? Si está en Windows y los números no cambiarán a tiempo, simplemente coloque su archivo de texto en los recursos del programa usando el enlazador de recursos, y léalo en su código.

3

Puede usar el comando xxd con la opción -i para convertir cualquier archivo a un vector de caracteres en C. Si está en Windows, puede buscar usarlo en Cygwin.

0

No es la solución (esto se dio antes) pero: no lo coloque en un archivo de encabezado. Escriba un encabezado, que define una función que devuelve una matriz. Luego impleméntalo en un archivo .c. De lo contrario, terminarás en un lío de compilación ...

0

Simplemente haz una cadena de tantos caracteres en tu programa ejecutable, y luego haz que otra sección del programa se abra como un archivo, toma los bytes, encuentra la cadena que ha compilado y la modifique como quiera directamente (asegúrese de poner una cadena única allí para ubicar el área real con la cadena en binario), puede necesitar cerrar el programa después de ejecutar otro programa que escribe los datos en el programa original y lo vuelve a ejecutar, cuando se vuelve a ejecutar el programa original puede leer los nuevos valores escritos de la cadena que se declaró en su binario y usar eso para realizar cualquier tarea.

Cuestiones relacionadas