質問
SQLite を使用する C++ プログラムがあります。SQL クエリを別のファイル (プレーンテキスト ファイル) に保存したいと考えています。 ない ソース コード ファイル -- ただし、そのファイルをリソースのように実行可能ファイルに埋め込みます。
(これは Linux 上で実行する必要があるため、私の知る限り実際のリソースとして保存することはできません。ただし、Windows 用であれば完璧でしょう。)
それを行う簡単な方法はありますか、それとも Linux 用に独自のリソース システムを作成する必要がありますか?(簡単にできますが、かなり時間がかかります。)
解決
objcopy を使用すると、ファイルの内容をプログラムで使用できるシンボルにバインドできます。たとえば、次を参照してください。 ここ 詳細については。
他のヒント
いつでも小さなプログラムやスクリプトを作成して、テキスト ファイルをヘッダー ファイルに変換し、ビルド プロセスの一部として実行できます。
マクロを使用します。技術的には、そのファイルは次のようになります ソースコード ファイルですが、このようにはなりません。例:
//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
後で、そのファイルに対して同じファイルであらゆる種類の他の処理を実行できます。たとえば、配列とそのハッシュ マップが必要な場合は、別のジョブを実行するように Q を再定義して、それで完了することができます。
ファイルのクロスプラットフォーム埋め込みに使用したサンプルを次に示します。かなり単純ですが、おそらくうまくいくでしょう。
また、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;
}
少し見苦しいですが、いつでも次のようなものを使用できます。
const char *query_foo = #include "query_foo.txt" const char *query_bar = #include "query_bar.txt"
ここで、query_foo.txt には引用符で囲まれたクエリ テキストが含まれます。
これは、リソース ファイルを、16 進形式のリソース ファイルの内容を含む char 配列が 1 つだけ定義された C ソース ファイルに変換することで行われることを確認しました (悪意のある文字による問題を回避するため)。この自動生成されたソース ファイルは、コンパイルされてプロジェクトにリンクされるだけです。
各リソース ファイルの C ファイルをダンプするコンバータの実装と、リソースにアクセスするためのいくつかのファサード関数の作成は非常に簡単です。