17

我有一个使用 SQLite 的 C++ 程序。我想将 SQL 查询存储在一个单独的文件中——一个纯文本文件,而不是源代码文件——但将该文件像资源一样嵌入到可执行文件中。

(这必须在 Linux 上运行,所以据我所知,我不能将它存储为实际资源,但如果它适用于 Windows,那将是完美的。)

有什么简单的方法可以做到这一点,或者它会有效地要求我为 Linux 编写自己的资源系统吗?(很容易,但需要更长的时间。)

4

6 回答 6

25

您可以使用 objcopy 将文件的内容绑定到您的程序可以使用的符号。例如,请参阅此处了解更多信息。

于 2008-09-16T14:17:44.077 回答
4

使用宏。从技术上讲,该文件将是源代码文件,但看起来不像这样。例子:

//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 来完成另一项工作并完成它。

于 2008-09-16T14:11:27.633 回答
3

您始终可以编写一个小程序或脚本来将文本文件转换为头文件,并将其作为构建过程的一部分运行。

于 2008-09-16T14:12:52.357 回答
2

这是我们用于跨平台嵌入文件的示例。这很简单,但可能对你有用。

您可能还需要更改它在 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;
}
于 2008-09-16T15:34:59.633 回答
1

它有点难看,但你总是可以使用类似的东西:

常量字符 *query_foo =
#include "query_foo.txt"

常量字符 *query_bar =
#include "query_bar.txt"

其中 query_foo.txt 将包含引用的查询文本。

于 2008-09-16T14:12:00.613 回答
0

我已经看到这是通过将资源文件转换为 C 源文件来完成的,该文件只定义了一个包含十六进制格式的资源文件内容的 char 数组(以避免恶意字符的问题)。然后简单地编译这个自动生成的源文件并将其链接到项目。

实现转换器来为每个资源文件转储 C 文件应该很容易,也应该很容易编写一些外观函数来访问资源。

于 2008-09-16T14:15:31.290 回答