题
我有一个使用 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 将包含引用的查询文本。
我发现这是通过将资源文件转换为 C 源文件来完成的,其中仅定义一个字符数组,其中包含十六进制格式的资源文件内容(以避免恶意字符出现问题)。然后简单地编译此自动生成的源文件并将其链接到项目。
实现转换器来为每个资源文件转储 C 文件以及编写一些用于访问资源的外观函数应该非常容易。
不隶属于 StackOverflow