significado - tipos de datos en c++
Incrustar datos en un programa C++ (6)
Tengo un programa en C ++ que usa SQLite. Quiero almacenar las consultas SQL en un archivo separado, un archivo de texto plano, no un archivo de código fuente, pero incruste ese archivo en el archivo ejecutable como un recurso.
(Esto tiene que ejecutarse en Linux, por lo que no puedo almacenarlo como un recurso real hasta donde yo sé, aunque sería perfecto si fuera para Windows.)
¿Hay alguna forma simple de hacerlo, o me requerirá efectivamente escribir mi propio sistema de recursos para Linux? (Fácilmente posible, pero tomaría mucho más tiempo).
Aquí hay una muestra que usamos para el arrastre multiplataforma de archivos. Es bastante simplista, pero probablemente funcione para ti.
También es posible que deba cambiar la forma en que maneja las alimentaciones de línea en la función escapeLine.
#include <string>
#include <iostream>
#include <fstream>
#include <cstdio>
using namespace std;
std::string escapeLine( std::string orig )
{
string retme;
for (unsigned int i=0; i<orig.size(); i++)
{
switch (orig[i])
{
case ''//':
retme += "////";
break;
case ''"'':
retme += "///"";
break;
case ''/n'': // Strip out the final linefeed.
break;
default:
retme += orig[i];
}
}
retme += "//n"; // Add an escaped linefeed to the escaped string.
return retme;
}
int main( int argc, char ** argv )
{
string filenamein, filenameout;
if ( argc > 1 )
filenamein = argv[ 1 ];
else
{
// Not enough arguments
fprintf( stderr, "Usage: %s <file to convert.mel> [ <output file name.mel> ]/n", argv[0] );
exit( -1 );
}
if ( argc > 2 )
filenameout = argv[ 2 ];
else
{
string new_ending = "_mel.h";
filenameout = filenamein;
std::string::size_type pos;
pos = filenameout.find( ".mel" );
if (pos == std::string::npos)
filenameout += new_ending;
else
filenameout.replace( pos, new_ending.size(), new_ending );
}
printf( "Converting /"%s/" to /"%s/"/n", filenamein.c_str(), filenameout.c_str() );
ifstream filein( filenamein.c_str(), ios::in );
ofstream fileout( filenameout.c_str(), ios::out );
if (!filein.good())
{
fprintf( stderr, "Unable to open input file %s/n", filenamein.c_str() );
exit( -2 );
}
if (!fileout.good())
{
fprintf( stderr, "Unable to open output file %s/n", filenameout.c_str() );
exit( -3 );
}
// Write the file.
fileout << "tempstr = ";
while( filein.good() )
{
string buff;
if ( getline( filein, buff ) )
{
fileout << "/"" << escapeLine( buff ) << "/"" << endl;
}
}
fileout << ";" << endl;
filein.close();
fileout.close();
return 0;
}
Es un poco feo, pero siempre puedes usar algo como:
const char *query_foo = #include "query_foo.txt" const char *query_bar = #include "query_bar.txt"
Donde query_foo.txt contendría el texto de consulta entre comillas.
Esto lo he visto convirtiendo el archivo de recursos en un archivo fuente en C con solo una matriz char definida que contiene el contenido del archivo de recursos en formato hexadecimal (para evitar problemas con los caracteres maliciosos). Este archivo fuente generado automáticamente se compila y vincula al proyecto.
Debería ser bastante fácil implementar el convertidor para volcar el archivo C para cada archivo de recursos, así como para escribir algunas funciones de fachada para acceder a los recursos.
Puede usar objcopy para vincular el contenido del archivo a un símbolo que su programa puede usar. Ver, por ejemplo, aquí para más información.
Siempre puede escribir un pequeño programa o script para convertir su archivo de texto en un archivo de cabecera y ejecutarlo como parte de su proceso de compilación.
Usa macros. Técnicamente, ese archivo sería un archivo de código fuente, pero no se vería así. Ejemplo:
//queries.incl - SQL queries
Q(SELECT * FROM Users)
Q(INSERT [a] INTO Accounts)
//source.cpp
#define Q(query) #query,
char * queries[] = {
#include "queries.incl"
};
#undef Q
Más adelante, podría hacer todo tipo de otro procesamiento en ese archivo con el mismo archivo, digamos que desea tener una matriz y un mapa hash de ellos, podría redefinir Q para hacer otro trabajo y terminar con él.